Skip to content

fix(server): answer every process-generated error with the envelope - #871

Merged
remyluslosius merged 2 commits into
mainfrom
fix/error-envelope-everywhere
Sep 21, 2026
Merged

remyluslosius merged 2 commits into
mainfrom
fix/error-envelope-everywhere

Conversation

@remyluslosius

Copy link
Copy Markdown
Contributor

Summary

CP bugs/doing/OW-063. Contract first, then code, then the guide.

Contract. system-http-server 1.5.0 adds C-15: every 4xx or 5xx the OpenWatch process generates carries the canonical envelope, including the responses no handler produces (unmatched /api/ path 404, method not allowed 405, parameter binding 400); a parameter message names the parameter and never echoes the rejected value or parser text; intermediary bodies are out of scope and clients must tolerate them. AC-20 covers the three cases plus a structural walk. api-events-stream 1.1.1 restates AC-02 for the envelope (the SSE handler's early 400 was plain text).

Code.

  • request_errors.go: an ErrorHandlerFunc for the generated router mapping RequiredParamError, RequiredHeaderError, InvalidParamFormatError, TooManyValuesForParamError, UnescapedCookieParamError and UnmarshalingParamError to request.missing_parameter or request.invalid_parameter; the message carries the parameter name only. server.go mounts the router with HandlerWithOptions and that handler; the 405 handler uses writeError.
  • spa.go: the /api/ fallthrough answers request.not_found; the non-GET branch answers request.method_not_allowed.
  • sse_handler.go: the three pre-stream exits use writeError (server.unavailable, request.missing_parameter, server.internal).

Tests. TestRequestErrors_EnvelopeEverywhere (AC-20): GET /api/v1/definitely-not-a-route 404, DELETE /api/v1/health 405, GET /api/v1/audit/events?limit=abc 400 naming limit and not containing abc; each with application/json and X-Correlation-Id. Plus a source walk that fails on any bare http.Error in internal/server outside tests and generated code. sse_handler_test.go AC-02 updated to the envelope.

Guide. The error section states the behavior and keeps the client guidance for non-JSON infrastructure errors. Merge after #870 (OW-065), whose sentence about the three plain-text cases this paragraph supersedes; I will refresh on conflict.

Checks

go test ./internal/server/ green (165 s, dedicated test DB); make spec-check 121/121, 100%; doc style clean; pre-commit and pre-push hooks passed.

Candidate impact

v0.8.0-rc.5 is immutable and carries the old behavior; nothing here changes it.

Three responses the process generated were text/plain: an unmatched /api/
path (404), a method the route does not accept (405), and a parameter
that fails to bind before the handler runs, where the generated router's
default wrote the parser's own error text, rejected value included. Three
more sat in the SSE handler before the stream starts. A client that parses
every non-2xx as the envelope failed on all of them and could not tell an
OpenWatch 404 from a proxy's.

Contract first: system-http-server 1.5.0 adds C-15 (every 4xx or 5xx the
process generates carries the envelope; a parameter message names the
parameter and never echoes the value; intermediary bodies are out of
scope and clients must tolerate them) and AC-20. api-events-stream 1.1.1
restates AC-02 for the envelope.

The router is mounted with an ErrorHandlerFunc that maps the generated
error types to request.missing_parameter or request.invalid_parameter;
the SPA fallback and the 405 handler use writeError; the SSE handler's
three early exits use it too. AC-20 exercises the three cases end to end
(status, Content-Type, X-Correlation-Id, code, message naming the
parameter and not the value) and walks internal/server for any bare
http.Error call so a new plain-text error fails the criterion. The API
guide's error section states the behavior and keeps the client guidance
for non-JSON infrastructure errors.

CP: bugs/doing/OW-063
@remyluslosius
remyluslosius merged commit 17531ee into main Sep 21, 2026
14 checks passed
@remyluslosius
remyluslosius deleted the fix/error-envelope-everywhere branch September 21, 2026 22:58
remyluslosius added a commit that referenced this pull request Sep 22, 2026
The error section takes main's paragraph: every process-generated
error now carries the envelope (#871 merged), so this branch's
sentence saying three were plain text is dropped. The audit-export
limitation sentence stays until #872 lands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant