Error pages outside forms are bare text with no way back #382

Open
opened 2026-10-01 22:06:18 +02:00 by clawbot · 2 comments
Collaborator

Owner's request, #377 (chat, 2026-10-01):

audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested).

What is wrong: every error outside a form is a bare plain-text page, with no page frame, no navigation bar and no link back. The audit reached them by opening a webhook that had just been deleted, a target ID that does not exist, and a mistyped path. Each shows only "404 page not found".

  • "404 page not found" comes from http.NotFound throughout internal/handlers.
  • "Bad request", "Forbidden" and "Internal server error" come from http.Error and serverError in internal/handlers/handlers.go.
  • "Forbidden - invalid CSRF token" comes from internal/middleware/csrf.go. A form left open in a tab long enough can hit it.
  • "The server is busy verifying credentials. Please try again." comes from internal/handlers/profile.go.

Validation errors on forms are not part of this issue. They belong on the form itself (#381 and #370).

Definition of done:

  • Every admin page route answers 400, 403, 404 and 500 with a rendered page in the normal layout. The page gives a one-line plain explanation and links back to the webhook list, or to sign-in when nobody is signed in. Status codes are unchanged.
  • The receiver at the inbound entrypoint URL, the healthcheck and /metrics keep their plain responses.
  • The pages show no more internal detail than the text does today.
  • Tests: a missing webhook, a missing target, an unknown path and a bad CSRF token each render the page, with the right status and the link back.

PRIORITY: from the owner's audit request of 1 October (#377), in the tier of #367 to #376.

Model: opus-5-5

Owner's request, https://git.eeqj.de/sneak/webhooker/issues/377 (chat, 2026-10-01): > audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested). What is wrong: every error outside a form is a bare plain-text page, with no page frame, no navigation bar and no link back. The audit reached them by opening a webhook that had just been deleted, a target ID that does not exist, and a mistyped path. Each shows only "404 page not found". - "404 page not found" comes from `http.NotFound` throughout `internal/handlers`. - "Bad request", "Forbidden" and "Internal server error" come from `http.Error` and `serverError` in `internal/handlers/handlers.go`. - "Forbidden - invalid CSRF token" comes from `internal/middleware/csrf.go`. A form left open in a tab long enough can hit it. - "The server is busy verifying credentials. Please try again." comes from `internal/handlers/profile.go`. Validation errors on forms are not part of this issue. They belong on the form itself (https://git.eeqj.de/sneak/webhooker/issues/381 and https://git.eeqj.de/sneak/webhooker/issues/370). Definition of done: - Every admin page route answers 400, 403, 404 and 500 with a rendered page in the normal layout. The page gives a one-line plain explanation and links back to the webhook list, or to sign-in when nobody is signed in. Status codes are unchanged. - The receiver at the inbound entrypoint URL, the healthcheck and `/metrics` keep their plain responses. - The pages show no more internal detail than the text does today. - Tests: a missing webhook, a missing target, an unknown path and a bad CSRF token each render the page, with the right status and the link back. PRIORITY: from the owner's audit request of 1 October (https://git.eeqj.de/sneak/webhooker/issues/377), in the tier of https://git.eeqj.de/sneak/webhooker/issues/367 to https://git.eeqj.de/sneak/webhooker/issues/376. Model: opus-5-5
clawbot self-assigned this 2026-10-01 22:06:18 +02:00
Author
Collaborator

Plan. The issue body is the brief. One error template in the normal layout, and one helper in internal/handlers that renders it with a status code and a fixed one-line explanation; every http.NotFound, http.Error and serverError on an admin page route goes through it, as does the CSRF failure in the middleware and the router's not-found handler for unknown paths. The page links back to the webhook list, or to sign-in when nobody is signed in. The receiver, the healthcheck and /metrics keep their plain responses. No more internal detail than today. It rebases onto #378's paths if that lands first.

Model: opus-5-5

Plan. The issue body is the brief. One error template in the normal layout, and one helper in `internal/handlers` that renders it with a status code and a fixed one-line explanation; every `http.NotFound`, `http.Error` and `serverError` on an admin page route goes through it, as does the CSRF failure in the middleware and the router's not-found handler for unknown paths. The page links back to the webhook list, or to sign-in when nobody is signed in. The receiver, the healthcheck and `/metrics` keep their plain responses. No more internal detail than today. It rebases onto https://git.eeqj.de/sneak/webhooker/pulls/378's paths if that lands first. Model: opus-5-5
Author
Collaborator

Built in #408. Every 400, 403, 404 and 500 on an admin page, unknown paths and a refused form token included, now answers with an error page in the normal layout: one fixed line for the status and a link back to the webhook list, or to sign-in when nobody is signed in. Status codes are unchanged; the receiver, the healthcheck and /metrics stay plain. If the error page itself cannot render, the answer is the same status in plain text.

  • Judgement call: on the page for an unknown path outside every route group the navbar leaves out Logout, because no form token is issued there and a logout without one is refused.
  • Judgement call: the line is fixed per status, so a refused form token and another user's profile share the 403 line; the profile page's busy answer (503) uses the page too.
  • Not changed: form validation messages (#381, #370), the 413 and 429 answers from the middleware, and the 500 written after a panic stay plain text.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/webhooker/pulls/408. Every 400, 403, 404 and 500 on an admin page, unknown paths and a refused form token included, now answers with an error page in the normal layout: one fixed line for the status and a link back to the webhook list, or to sign-in when nobody is signed in. Status codes are unchanged; the receiver, the healthcheck and `/metrics` stay plain. If the error page itself cannot render, the answer is the same status in plain text. - Judgement call: on the page for an unknown path outside every route group the navbar leaves out Logout, because no form token is issued there and a logout without one is refused. - Judgement call: the line is fixed per status, so a refused form token and another user's profile share the 403 line; the profile page's busy answer (503) uses the page too. - Not changed: form validation messages (https://git.eeqj.de/sneak/webhooker/issues/381, https://git.eeqj.de/sneak/webhooker/issues/370), the 413 and 429 answers from the middleware, and the 500 written after a panic stay plain text. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#382