Skip to content

fix(runtime): carry spec-validation issues + 422 through metadata save/publish errors - #2589

Merged
os-zhuang merged 1 commit into
mainfrom
feat/meta-validation-issues
Jul 4, 2026
Merged

fix(runtime): carry spec-validation issues + 422 through metadata save/publish errors#2589
os-zhuang merged 1 commit into
mainfrom
feat/meta-validation-issues

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why (UX eval #4 — validation up-front + inline errors)

When a Studio user saves an invalid metadata draft, protocol.saveMetaItemalready validates it against its spec Zod schema and throws a rich, field-anchored error:

status: 422, code: 'invalid_metadata',
issues: [{ path: 'fields.amount.type', message: 'Required', code: 'invalid_type' }, ...]

…but the HTTP dispatcher threw all of that away:

  • save (http-dispatcher.ts PUT catch) did this.error(e.message, 400) — hardcoded 400, issues dropped;
  • publish (publishPackageDrafts per-draft catch) flattened each failure to { type, name, error }issues dropped.

So the Studio could only show a generic "failed validation" banner / toast, never point at the offending field. This is the server half of making validation errors land on the field, at the save/publish moment (the #1 "silent failure" UX theme).

What

  • New errorFromThrown(e, fallbackStatus) dispatcher helper — preserves the error's own status (validation now surfaces as 422, not a downgraded 400) and attaches { code, issues } under error.details when present. Errors carrying neither behave exactly as before. Wired into the metadata save and publish catch sites.
  • publishPackageDrafts now carries issues into each failed[] entry.

Resulting error body on a failed save:

{ "success": false, "error": {
"message": "[invalid_metadata] object/bad failed spec validation: fields.amount.type: Required",
"code": 422,
"details": { "code": "invalid_metadata", "issues": [{ "path": "fields.amount.type", "message": "Required", "code": "invalid_type" }] }
} }

Compatibility

Purely additive to the error payload (error.details.issues). The only behavior change is the more-correct 422 (was 400) for a failed metadata save — 422 is already the validation status the protocol raises and is used elsewhere. Plain errors (no status/issues) are unchanged; the existing "should return error if save fails" test still asserts 400.

Tests

New dispatcher test: a saveMetaItem that throws a 422 / invalid_metadata / issues[...] error yields a 422 response with error.details.issues preserved (path intact). Full @objectstack/runtime (448) + @objectstack/metadata-protocol (8) suites green; both packages build (incl. DTS).

The objectui half (extract error.details.issues → show field-anchored in the Studio) follows in a companion objectui PR; verified end-to-end there.

🤖 Generated with Claude Code

…ata save/publish errors
protocol.saveMetaItem throws a field-anchored spec-validation error (status 422,
code invalid_metadata, issues:[{path,message,code}]), but the HTTP dispatcher
collapsed it to a single message (save even hardcoded 400) and publish dropped
issues from each failed[] entry. The Studio could therefore only show a generic
banner, never point at the offending field.
- Add errorFromThrown(e, fallback) dispatcher helper: preserves the error's own
status (validation now surfaces as 422, not a downgraded 400) and attaches
{code, issues} under error.details when present; unchanged for plain errors.
Wired into the meta save (PUT /meta/:type/:name) and publish
(POST /packages/:id/publish-drafts) catch sites.
- publishPackageDrafts carries issues into each failed[] entry.
Server half of "surface validation at the save/publish moment, on the field".
Additive to the error payload; only behavior change is the more-correct 422.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 4, 2026 3:45pm

Request Review

@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation tests tooling labels Jul 4, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/metadata-protocol, @objectstack/runtime.

16 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/chatbot-integration.mdx(via @objectstack/runtime)
  • content/docs/api/index.mdx(via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx(via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx(via packages/runtime)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/runtime)
  • content/docs/deployment/cloud-artifact-api.mdx(via packages/runtime)
  • content/docs/deployment/index.mdx(via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx(via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx(via @objectstack/runtime)
  • content/docs/permissions/authentication.mdx(via @objectstack/runtime)
  • content/docs/plugins/packages.mdx(via @objectstack/runtime)
  • content/docs/protocol/objectos/http-protocol.mdx(via @objectstack/runtime)
  • content/docs/protocol/objectos/index.mdx(via @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx(via @objectstack/runtime)
  • content/docs/releases/implementation-status.mdx(via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit e3498fb into mainJul 4, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the feat/meta-validation-issues branch July 4, 2026 15:46
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang