Skip to content

docs(error-catalog): VALUE_TOO_LONG / VALUE_TOO_SHORT name the field-level codes that really arrive - #20004

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-19879-error-catalog-value-length
Sep 27, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-19879-error-catalog-value-length

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #19879
Clause-②: no

What

content/docs/api/error-catalog.mdx, the VALUE_TOO_LONG and VALUE_TOO_SHORT entries only. Both entries gave a live cause and a fix, as if a client could branch on the code. No producer emits either code. Both entries now say so, following the shape the INVALID_FORMAT entry got in #19878: the code is reserved, no route emits it today, and a length miss arrives as a field-level max_length / min_length entry. Each entry now says where that entry rides on each path: 400 VALIDATION_FAILED with fields[] for record writes and Zod-parsed request bodies (top-level on /data, under details through the runtime dispatcher), and 400 SETTINGS_VALIDATION with details.fields[] for a settings write. The fix line names both envelopes. Both entries stay because the enum still declares the codes.

Evidence (measured on origin/main e8f163fc)

  • No producer. git grep -nE 'VALUE_TOO_(LONG|SHORT)' outside tests hits only the enum members packages/spec/src/api/errors.zod.ts:58-59, the baseline rows scripts/error-status-unpinned-baseline.json:27-28, this page, the generated content/docs/references/** pages, and ADR-0114, which records these members as a known wart. A grep for other spellings (VALUE_TOO, TOO_LONG, TOO_SHORT) finds only the unrelated PASSWORD_TOO_SHORT in a plugin-auth test. Positive control: INVALID_FORMAT hits errors.zod.ts:57.
  • Record writes. packages/objectql/src/validation/record-validator.ts:695-699 sends fail('max_length', { maxLength, actual }) and fail('min_length', { minLength, actual }) for BOUNDED_STRING_FIELD_TYPES. buildFieldError puts that object on the wire as fields[].constraint, and the envelope's top-level code is VALIDATION_FAILED (VALIDATION_FAILED_CODE, :195).
  • Zod-parsed request bodies. packages/spec/src/api/zod-issues-to-fields.ts:74-81 maps too_small / too_big to min_length / max_length when the value is not a number, bigint, date, array or set. Numbers and dates map to min_value / max_value, and arrays and sets to min_items / max_items. That is why the page says "a string". The REST routes that use this send code: 'VALIDATION_FAILED' (for example packages/rest/src/rest-server.ts:8960-8963).
  • Settings writes (a different envelope). packages/services/service-settings/src/settings-service.ts:397-400 returns max_length / min_length with constraint { minLength?, maxLength?, actual } for a settings value outside its declared length window. :2145 pushes it into the errors list, and :2167 throws SettingsValidationError (settings-service.types.ts:583-584, code = 'SETTINGS_VALIDATION'). packages/services/service-settings/src/settings-routes.ts:215-217 serves it as sendError(res, 400, 'SETTINGS_VALIDATION', …, { details: { namespace, fields } }), and packages/types/src/response-envelope.ts sendError writes that as { success: false, error: { code, message, details } }. So a settings length miss is top-level SETTINGS_VALIDATION with the entry in error.details.fields[], not VALIDATION_FAILED.
  • Where VALIDATION_FAILED puts the list. On the /data routes it is flat (packages/rest/src/error-response.ts:1152-1160, mapDataError: top-level fields). Through the runtime dispatcher it is nested (packages/runtime/src/dispatcher-plugin.ts:645, validationFailureDetails: details.fields). The page's own VALIDATION_FAILED callout already documents both, so the entries link to it rather than restating it.
  • The field-level spellings are the same on all three paths: max_length / min_length. The envelope differs: VALIDATION_FAILED for records and Zod bodies, SETTINGS_VALIDATION for settings.

Not touched

Changeset

None. This is a docs-only change under content/docs/, and no published package's files[] changes, so it falls under skip-changeset. The PM seat applies the label.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands from the merge-base change set (1 path). All 41 derived commands ran on HEAD 37431df1 and exited 0. The derivation is unchanged from the first head, ab8b19ea. They include pnpm check:doc-authoring, pnpm check:doc-anchors, pnpm check:nul-bytes, pnpm check:error-status-conformance, pnpm check:docs-spec-enumerations and pnpm --filter @objectstack/spec run check:docs. The prerequisite closures (lint / formula / client-react, which pulls in spec) were built under the verify lock first. Reconciliation with --ran and the recorded exit codes: 41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero). No package source changed, so no package tests or typecheck are owed.

Rework (PM review)

The first head said every length miss arrives in VALIDATION_FAILED, which is wrong for settings writes. The second commit, 37431df1, names SETTINGS_VALIDATION + details.fields[] for that path in both the Cause and the Fix lines. The #validation_failed link resolves: check:doc-anchors passes, with 377 fragment links resolved.

Acceptance notes

  • The page's intro counts "52 error codes reachable on the wire", but the page carries 53 code headings, and several of them are reserved codes with no emitter (INVALID_FORMAT, INVALID_REFERENCE, and now these two). Whether that count should include reserved codes is a question for the line PR feat(spec)!: retire CONCURRENT_LIMIT_EXCEEDED from StandardErrorCode #19957 already edits. It is not changed here.

Generated by Claude Code

…level codes that really arrive

No producer emits either top-level code; a length miss is refused inside
VALIDATION_FAILED with fields[].code max_length / min_length (record
validator, settings values, Zod-parsed request bodies). Both entries now
say so and tell clients to branch on VALIDATION_FAILED + fields[].code,
mirroring the INVALID_FORMAT entry.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 24, 2026
…entry

A settings write refuses a length miss as 400 SETTINGS_VALIDATION with the
entry in details.fields[], not VALIDATION_FAILED; record writes and
Zod-parsed bodies answer VALIDATION_FAILED with the entry in fields[]
(top-level on /data, under details via the runtime dispatcher). Both
entries and their Fix lines now name both envelopes.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 37431df1c5447e898bff3befe718aa9028ff0698

① Derived judgments

Measured on origin/main e8f163fc. The PR head changes one file, content/docs/api/error-catalog.mdx :215-251: the VALUE_TOO_LONG and VALUE_TOO_SHORT entries only.

  1. "No route emits VALUE_TOO_LONG / VALUE_TOO_SHORT today" — TRUE. Non-test git grep over packages/ and apps/ hits only the enum declaration packages/spec/src/api/errors.zod.ts:58-59. Positive control: 'VALIDATION_FAILED' hits packages/rest/src/error-response.ts:1152,1157,1812.
  2. Record-write length miss is field-level max_length / min_length with constraint carrying maxLength/minLength and actual — TRUE. packages/objectql/src/validation/record-validator.ts:693-699; fail at :611-617 routes to buildFieldError, which ships constraint (:395).
  3. On the /data routes the entry rides top-level in fields[] with 400 VALIDATION_FAILED — TRUE. packages/rest/src/error-response.ts:1152-1160.
  4. A Zod-parsed request body answers 400 VALIDATION_FAILED with max_length / min_length — TRUE. Mapper packages/spec/src/api/zod-issues-to-fields.ts:72-80. All seven /data Zod gates in packages/rest/src/rest-server.ts answer top-level fields. Runtime domain routes go through validationFailure(...) (packages/types/src/validation-failure.ts:76-80). No safeParse site answering another code: was found (control: the seven sites).
  5. Under details when the runtime dispatcher serves it — TRUE. packages/runtime/src/dispatcher-plugin.ts:645 and :790-800; the page's existing VALIDATION_FAILED callout already states error.details.fields[] for this door.
  6. A settings write answers 400 SETTINGS_VALIDATION with the entry in details.fields[] — TRUE. packages/services/service-settings/src/settings-service.ts:397,400, thrown at :2167 (settings-service.types.ts:584); settings-routes.ts:215-217.
  7. Fix lines (branch on VALIDATION_FAILED + fields[].code, or SETTINGS_VALIDATION + details.fields[].code) — TRUE. This follows the page's INVALID_FORMAT / INVALID_REFERENCE pattern.
  8. #validation_failed anchor resolves — TRUE. The heading is at :77, and the head's Check Documentation Links check is success.
  9. No parser reads per-entry Cause/Fix lines — TRUE. scripts/check-error-status-conformance.mjs:54-56 reads only the Quick Reference rows and category headings.

Advisory, not a failing claim: the analytics dataset-selection door (packages/rest/src/analytics-selection-door.ts:148,171, from rest-server.ts:11157) is a Zod-parsed body that answers 400 VALIDATION_FAILED with details: { fields }. The placement sentence is correct for the two doors it names, but it is not exhaustive. The link to the VALIDATION_FAILED entry covers the gap: that entry's callout says placement "is decided by the door".

② Semver level

None (docs-only). One file under content/docs/. No package files[] references content/docs. No changeset, and none is warranted. skip-changeset is the correct disposition, but it is not applied yet: Check Changeset fails at "Require a changeset (or the skip-changeset label)".

③ Boundary flags

  • Governed surfaces: none touched. Governed Surface Queue Guard, the single-writer-path check and the card-claims-branch check are all success.
  • Open PR feat(spec)!: retire CONCURRENT_LIMIT_EXCEEDED from StandardErrorCode #19957 edits :6 (count 52 → 51) and deletes CONCURRENT_LIMIT_EXCEEDED at :470-477. This PR's single hunk, :215-251, touches neither, so there is no textual conflict.
  • Nothing misleads an AI author beyond the advisory in ①.
  • Check-runs at read time (37): Check Changeset failed (label missing). Test Core (1/6), Type Check · workspace, Type Check · consumer gates and Lint & Repo Gates were in progress. Every other check was success or path-skipped.

Implemented-by: claude/issue-19879-error-catalog-value-length
Reviewed-by: session_01VDtqoecgES7ScQYGbFVDRv

VERDICT: PASS

Landing still needs, separately from this verdict: the skip-changeset label, with Check Changeset re-run to green, and the four in-progress checks completing green on this head. Isolated at-tier reviewer, adopted by the domain:devx#1 seat.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Landing · director seat (summon #30 续, session_01AsCNgFBs8HCjwhyHQsFbx3) 2026-09-27T06:00Z, on the maintainer's 「12小时之前的pr什么情况帮我跟进到合并」.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 27, 2026 06:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 27, 2026
Merged via the queue into main with commit 836aad2 Sep 27, 2026
43 of 45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-19879-error-catalog-value-length branch September 27, 2026 06:21
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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant