Adding a port mapping makes the app detail page 500 forever (CSRFField inside range .Ports) #192

Closed
opened 2026-09-09 14:39:09 +02:00 by clawbot · 1 comment
Collaborator

What is wrong

Adding a port mapping to an app makes that app's detail page return 500 from then on. The port row is saved, and the only control that could remove it lives on the page that no longer renders, so the app cannot be recovered through the UI.

templates/app_detail.html:325, inside {{range .Ports}}:

<form method="POST" action="/apps/{{$.App.ID}}/ports/{{.ID}}/delete" ...>
{{ .CSRFField }}

Inside the range, . is a *models.Port, so .CSRFField does not exist. The labels block (line 190) and the volumes block (line 255) correctly use {{ $.CSRFField }}; only the ports block does not.

How to reproduce

Log in, open an app, scroll to Port Mappings, enter host 18090 / container 8080, click Add. The redirect back to /apps/<id> returns 500 "Internal Server Error", and so does every later load of that URL. Server log:

template execution failed
error="execute page template app_detail.html: template: app_detail.html:325:19:
executing \"content\" at <.CSRFField>: can't evaluate field CSRFField in type *models.Port"

The dashboard, the deployments page and /api/v1/apps/<id> still work, which is how you can tell the port row was written. Since Delete App and Delete Port are both only on the broken page, the only way out is editing the database by hand.

What acceptable looks like

Adding a port mapping renders the app detail page normally, the mapping appears in the table with a working Delete button, and the mapping is applied to the container on the next deploy.

Change line 325 to {{ $.CSRFField }}. A rendering test that walks every template with a populated app — one that has at least one port, label, volume and env var — would catch this class of mistake; the same bug was fixed once before on the dashboard (see the 2026-02-26 entry in TODO.md), so a test is worth more than the one-character fix.

Model: opus-5

## What is wrong Adding a port mapping to an app makes that app's detail page return 500 from then on. The port row is saved, and the only control that could remove it lives on the page that no longer renders, so the app cannot be recovered through the UI. `templates/app_detail.html:325`, inside `{{range .Ports}}`: ``` <form method="POST" action="/apps/{{$.App.ID}}/ports/{{.ID}}/delete" ...> {{ .CSRFField }} ``` Inside the range, `.` is a `*models.Port`, so `.CSRFField` does not exist. The labels block (line 190) and the volumes block (line 255) correctly use `{{ $.CSRFField }}`; only the ports block does not. ## How to reproduce Log in, open an app, scroll to Port Mappings, enter host `18090` / container `8080`, click Add. The redirect back to `/apps/<id>` returns 500 "Internal Server Error", and so does every later load of that URL. Server log: ``` template execution failed error="execute page template app_detail.html: template: app_detail.html:325:19: executing \"content\" at <.CSRFField>: can't evaluate field CSRFField in type *models.Port" ``` The dashboard, the deployments page and `/api/v1/apps/<id>` still work, which is how you can tell the port row was written. Since Delete App and Delete Port are both only on the broken page, the only way out is editing the database by hand. ## What acceptable looks like Adding a port mapping renders the app detail page normally, the mapping appears in the table with a working Delete button, and the mapping is applied to the container on the next deploy. Change line 325 to `{{ $.CSRFField }}`. A rendering test that walks every template with a populated app — one that has at least one port, label, volume and env var — would catch this class of mistake; the same bug was fixed once before on the dashboard (see the 2026-02-26 entry in `TODO.md`), so a test is worth more than the one-character fix. Model: opus-5
Author
Collaborator

Fixed in #193: the port-mapping delete form now uses the page-level CSRF field ($.CSRFField) inside the range. Verified by adding a port mapping and reloading the page.

Model: opus-4-8

Fixed in https://git.eeqj.de/sneak/upaas/pulls/193: the port-mapping delete form now uses the page-level CSRF field (`$.CSRFField`) inside the range. Verified by adding a port mapping and reloading the page. Model: opus-4-8
sneak closed this issue 2026-09-10 11:17:43 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/upaas#192