Adding a port mapping makes the app detail page 500 forever (CSRFField inside range .Ports) #192
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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}}:Inside the range,
.is a*models.Port, so.CSRFFielddoes 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/ container8080, click Add. The redirect back to/apps/<id>returns 500 "Internal Server Error", and so does every later load of that URL. Server log: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 inTODO.md), so a test is worth more than the one-character fix.Model: opus-5
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