You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(client): retire the pre-#3842 parking-spot read; category/retryable read the declared spot (#4006, #4007)
- err.code no longer falls back to error.details.code. The "newer SDK,
older server" pairing that read served is not a supported deployment
(SDK and server ship as a changesets fixed group), and ADR-0112
batches 1-2 renamed the code VALUES anyway — a code dug out of an old
server's parking spot matches no branch written against the current
catalog. Location-compat without value-compat protects nothing (#4007
maintainer ruling; ADR-0112 D5 amended in place).
- err.category / err.retryable now read from inside error, where
ApiErrorSchema declares them; the old top-level read yielded
undefined against every conformant server (ADR-0112 D9b, #4006).
- Tests: the "older server, newer SDK" pin flips to pin the retirement;
two new cases cover the D9b reads (present and absent).
- Docs: client-sdk.mdx / wire-format.mdx stop describing the retired
fallback; error-catalog.mdx's actions rejection example corrected to
the real wire (envelope assembly promotes the thrown code into
error.code — details carries fields only); v17.mdx notes the
retirement and uses post-rename spelling in the derived-map example.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u8vDQLWPJxBWQESznDpSj
`err.code` no longer falls back to the pre-#3842 parking spot (`error.details.code`). The "newer SDK, older server" pairing that read served is not a supported deployment (SDK and server ship as one fixed release group), and the ADR-0112 batch-1 rename changed the code values anyway — a code dug out of an old server's parking spot would match no branch written against the current catalog (#4007). `err.category` / `err.retryable` are now read from inside `error`, where `ApiErrorSchema` declares them; the old top-level read yielded `undefined` against every conformant server (#4006).
Copy file name to clipboardExpand all lines: docs/adr/0112-error-code-vocabulary-and-ledger.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -90,6 +90,8 @@ Nine rulings, D1–D9.
90
90
91
91
**D5 — One location, eventually: `error.code` carries the semantic code.** Target end-state, recorded here so the follow-ups have a fixed destination: the HTTP status lives on the transport and (optionally) `error.httpStatus`; `error.code` is always the semantic string; `error.details.code` and `error.type` are retired as code carriers. The dispatcher-occupation fix (#3689 sibling) and `ROUTE_NOT_FOUND`-in-`type` retirement land as follow-ups (Rollout, batch 3). The client's three-location probe is deleted only after both.
92
92
93
+
> **Amendment (2026-07-30, [#4007](https://github.com/objectstack-ai/objectstack/issues/4007)) — ruled and done.** With batch 3 landed, the client's parking-spot read (`error.details.code`) is deleted: SDK and server ship as a changesets fixed group, so the "newer SDK, older server" pairing it served is not a supported deployment — and batches 1–2 renamed the code *values* anyway, so a code dug out of an old server's parking spot would match no branch written against the current catalog; location-compat without value-compat protects nothing. The client's two remaining reads are the two *live* envelopes' declared spots (flat top-level `code`, wrapped `error.code`) — a present-tense fact, not a fallback chain; retiring the flat shape itself belongs to the envelope-convergence line (#3843 family), not this ADR. The D9b nesting fix (`category`/`retryable`, [#4006](https://github.com/objectstack-ai/objectstack/issues/4006)) landed in the same change.
94
+
93
95
**D6 — Field-level codes are explicitly a separate vocabulary, and the schema stops lying meanwhile.**`FieldErrorSchema.code` widens from `StandardErrorCode` to `z.string()` with a banner comment pointing at the follow-up issue. Widening is honest (emitters never complied) and prevents this ADR's rename from silently claiming field-level compliance it does not deliver. The field vocabulary (validator codes, import codes, Zod-passthrough, the `fields` vs `fieldErrors` naming, and a schema for the wire array) gets its own issue and, if the decision is non-obvious, its own ADR.
94
96
95
97
**D7 — `error-catalog.mdx` is generated from the spec.** The hand-written catalog is how docs and wire drifted apart in the first place (`docs/audits/2026-06-handwritten-docs-accuracy-followups.md:230` catalogues the casing drift; `:106` found a documented-only vocabulary with zero emitters). Generated docs are the only docs that cannot lie — and for AI authors, docs *are* context.
0 commit comments