mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-06 08:18:58 +00:00
Earlier refactor to a discriminated-union loader accidentally
discarded the plan's R5 error taxonomy. `apiJsonOrNull` throws a
body-less Response on non-ok statuses, so the loader's try/catch had
no way to recover the server's error envelope or the request_id for
500s. The initial-error render then collapsed all statuses into
either `<EmptyState kind="unknown">` (401/403) or a generic
InlineErrorBanner — losing the plan-specified copy for access denied,
transient failures, and 500 with request ID.
Fixes:
- Loader now uses `fetch` directly against the API path so the
response body is preserved on non-ok statuses.
- 404/501 still collapse to `{data: null, error: null}` (the empty-
envelope signal the UI maps to R4).
- Any other non-ok parses the body as JSON, extracts request_id from
either the top-level `request_id` field or the uniform error
envelope (`errors[0].request_id` or parsed out of
`errors[0].detail`), and threads it through `error.requestId`.
- Component's `initialError` branch now applies the full R5 taxonomy:
R5(c) access denied for 401/403 with the specific copy, R5(a)
retry banner for 429/503, R5(d) "Something went wrong. Request ID:
<id>. Contact support." for 500s, and a generic retryable banner
for any other 4xx.
Adds run-files.test.ts covering extractRequestId across the three
locations request_id can show up in a server error body (top-level,
errors[0].request_id, errors[0].detail regex).
The RunFilesErrorBoundary export stays in place as defense-in-depth
for React render crashes — the loader no longer throws, but ensuring
the route always has a fallback is cheap.
Refs docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md §
Unit 11 R5 taxonomy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| crates | ||
| packages/fabro-api-client | ||