Skip to content

fix(api): surface server error messages instead of a bare ✖ HTTP 400 - #10

Merged
akoso merged 2 commits into
mainfrom
fix/error-messages
Aug 1, 2026
Merged

fix(api): surface server error messages instead of a bare ✖ HTTP 400#10
akoso merged 2 commits into
mainfrom
fix/error-messages

Conversation

@akoso

@akoso akoso commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

What

Every non-2xx from the MNA API currently renders as a bare ✖ HTTP 400 — that blindness cost a full diagnostic round when variants add was broken. This makes the CLI print whatever the server actually said, defensively.

One implementation, in the openapi-fetch response middleware (src/api/client.ts), so every command benefits — no per-command patching. On a non-2xx the body is read once and a detail is derived in order:

  1. message — string, or a string array (NestJS validation convention) joined with ;
  2. error
  3. a raw non-JSON body, only if it is short (≤ 200 chars) and printable
  4. nothing

With a detail: ✖ HTTP 400 — location.coordinates must be { lat, lng }.
Without one: ✖ HTTP 400 — byte-for-byte today's output.

Degradation

Bodies with nothing usable in them fall back to the bare status line: today's production {statusCode, timestamp, path}, an empty body, a body stripped by a proxy, an HTML error page, and the intentionally bare 500. No undefined ever reaches the terminal.

--json

Unchanged and verified end-to-end against a stub server: errors go to stderr via reportAndExit, stdout stays completely empty on failure. Machine output stays machine output.

Tests

src/api/client.test.ts gains cases for message-as-string, message-as-array, error fallback, short non-JSON body, long/unprintable non-JSON body, empty body (reproduces today's exact output), message-less {statusCode, timestamp, path} body, and a bare 500.

Release gating

Version bumped to 0.3.1, but not tagged and not published. The release waits until travel-plans #127 — the server-side fix that stops the global exception filter from dropping HttpException payloads — is merged and deployed, so the improvement is real when it ships.

OpenAPI snapshot: deferred

#127 also adds flat address/latitude/longitude to the v1 event location DTO. Checked the live spec at https://api.mynextadventure.cloud/v1/openapi.json while preparing this: EventLocationV1Dto still has only googlePlaceId/name/formattedAddress/coordinates, and the live spec is otherwise byte-identical to the committed openapi.json. Snapshot left alone; a follow-up commit refreshes it and re-runs bun run codegen after the deploy.

Gates

bun run codegen, bun run typecheck (no diagnostics), bun run lint, bun test (160 pass / 0 fail), bun run build — all clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AsdP2hvt4XQhYxkdNREXUq

akoso and others added 2 commits August 1, 2026 22:51
Every non-2xx used to render as a bare `✖ HTTP 400`, which cost a full
diagnostic round when `variants add` was broken. The client now reads the
error body once and derives a detail from `message` (string, or a string
array joined with `; `), then `error`, then a short printable non-JSON
body — rendering `✖ HTTP 400 — <detail>` on the existing error path, so
every command benefits without per-command changes.

Bodies with nothing usable — today's production `{statusCode, timestamp,
path}`, an empty body, a stripped body, an HTML error page, or the
intentionally bare 500 — degrade to exactly the previous `✖ HTTP <status>`
output. `--json` behaviour is unchanged: errors go to stderr and stdout
stays empty, so machine output stays machine output.

Bumps the version to 0.3.1. The release itself waits until travel-plans
#127 is merged and deployed, so the improvement is real when it ships.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsdP2hvt4XQhYxkdNREXUq
… error messages)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsdP2hvt4XQhYxkdNREXUq
@akoso
akoso merged commit 10ce36f into main Aug 1, 2026
1 check passed
@akoso
akoso deleted the fix/error-messages branch August 1, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant