Skip to content

fix: await a remote JSON schema before validating - #19438

Open
pcbeingused333 wants to merge 1 commit into
payloadcms:mainfrom
pcbeingused333:fix/json-remote-schema-validation
Open

pcbeingused333 wants to merge 1 commit into
payloadcms:mainfrom
pcbeingused333:fix/json-remote-schema-validation

Conversation

@pcbeingused333

Copy link
Copy Markdown

Fixes #19399

A JSON field configured with only a remote jsonSchema (uri and fileMatch, no inline schema) accepts every value. validateJSONSchema assigned the result of fetchSchema without awaiting it. When schema is omitted, that result is a Promise. Zod's fromJSONSchema treats the Promise as an empty schema and safeParse succeeds for any value. The Promise was also written onto the field config, so the next validation saw a truthy schema, skipped the fetch, and kept accepting everything. The same missing await dropped a rejected fetch(undefined) when uri was absent, so that misconfiguration saved the value too, with an unhandled rejection.

fetchSchema is now awaited before the schema is compiled, and the resolved document is what gets cached on the field. JSONField['jsonSchema']['schema'] is optional, so the documented remote config type-checks. An inline schema passed together with uri is still used as-is and does not call fetch. A missing uri still goes through fetch; the rejection is returned as the validation message instead of being ignored.

packages/payload/src/fields/validateJSONSchema.spec.ts covers the three cases. On main, the remote-uri case and the missing-uri case fail: { a: "x" } is accepted, and the missing uri also surfaces an unhandled TypeError. With this change all three pass. The inline schema rejects a string where a number is required and does not fetch. The remote uri fetches once, rejects { a: "x" }, accepts { a: 1 }, and caches the schema object rather than a Promise. A failed fetch is reported instead of accepted.

This change was prepared with the help of an AI assistant (Claude Code).

A jsonSchema config with only a uri stored the fetch Promise on the field
and passed that Promise to zod, which accepts every value. Await the fetch
and allow schema to be omitted so the documented remote config type-checks.
@coderabbitai

coderabbitai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The JSON field type now allows jsonSchema.schema to be omitted. Validation awaits the schema returned by fetchSchema before assigning it. New tests cover inline schemas, fetched schemas, schema reuse, and fetch failure.

Changes: JSON Schema validation

Layer / File(s) Summary
Resolve and validate JSON schemas
packages/payload/src/fields/config/types.ts, packages/payload/src/fields/validateJSONSchema.ts, packages/payload/src/fields/validateJSONSchema.spec.ts
JSONField.jsonSchema.schema is optional. validateJSONSchema awaits fetchSchema before assigning its result. Tests cover inline and fetched schemas, reuse of a fetched schema, and a failed fetch when uri is absent.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related issues

  • payloadcms/payload#19401: The array-transform case remains unresolved; the change does not remove the jsonSchema collision described in the issue.

Suggested reviewers: alessiogr

Merge Risk: Low · up to 40b39

The validation change has no established merge-blocking code defect. Change the PR title to an allowed scope so its failing title check can pass.

Pre-merge checks: Passed 5

Check name Status Explanation
Description check Passed The description explains the bug, the missing await in validateJSONSchema, and the Promise being cached on the field config. It lists the fix: awaiting fetchSchema, making JSONField jsonSchema schema …
Linked Issues check Passed Scope: directly linked issue #19399 is open and is the only active target. Its coding requirements are: (1) a uri-only remote jsonSchema must be fetched, awaited, cached, and used to reject invalid va…
Out of Scope Changes check Passed The whole-PR diff against the merge base changes three files. Each change supports the linked issue #19399.

- packages/payload/src/fields/validateJSONSchema.ts: adds await to the fetchSchema call a…
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Title check Passed The title "fix: await a remote JSON schema before validating" matches the main change. The PR awaits the remote schema fetch in validateJSONSchema.ts before compiling it, caches the resolved schema, a…
Full details: Description check

Explanation

The description explains the bug, the missing await in validateJSONSchema, and the Promise being cached on the field config. It lists the fix: awaiting fetchSchema, making JSONField jsonSchema schema optional, and returning the failed fetch as a validation message. It also names the spec file and the three test cases. The description matches the changeset.

Full details: Linked Issues check

Explanation

Scope: directly linked issue #19399 is open and is the only active target. Its coding requirements are: (1) a uri-only remote jsonSchema must be fetched, awaited, cached, and used to reject invalid values; (2) JSONField['jsonSchema']['schema'] must allow omission; (3) a schema-without-uri misconfiguration must not silently accept values with an unhandled rejection.

Requirement 1 [#19399]: In packages/payload/src/fields/validateJSONSchema.ts at head, the line is now jsonSchema.schema = await fetchSchema(jsonSchema). The missing await is fixed, so Zod receives the resolved document, not a Promise. Because the resolved schema is written back to the field config, the next call takes the uri && schema branch and does not fetch again. The spec 'fetches a remote schema from uri...' asserts one fetch call, a rejected { a: 'x' }, a valid { a: 1 }, and that jsonSchema.schema is not a Promise.

Requirement 2 [#19399]: In packages/payload/src/fields/config/types.ts, schema is now schema?: JSONSchema4 with a comment that says it is fetched from uri when omitted. The fetchSchema parameter type is also optional.

Requirement 3 [#19399]: With uri absent, fetch(undefined) rejects. The rejection is now awaited inside the existing try block and returned through error.message, so the value is rejected. The spec 'reports a failed fetch...' covers this.

Inline schema with uri: the uri && schema branch still returns the inline schema without calling fetch. The spec 'rejects a value that violates an inline schema without fetching' covers this.

Residual uncertainty: this review did not search other consumers of jsonSchema.schema for code that assumes it is required. The type change could affect those sites. This does not affect the linked-issue behavior requirements.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff against the merge base changes three files. Each change supports the linked issue #19399.

  • packages/payload/src/fields/validateJSONSchema.ts: adds await to the fetchSchema call and makes the fetchSchema schema parameter optional. These changes implement the linked requirements.
  • packages/payload/src/fields/config/types.ts: makes jsonSchema.schema optional with a doc comment. This implements the documented remote-only config type.
  • packages/payload/src/fields/validateJSONSchema.spec.ts: adds three tests for inline schema, remote uri, and missing uri. These tests support the coding requirements.

No unrelated files, refactors, or behavior changes were found in the diff. The spec's helper functions serve the test cases only.

Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 3 files.

Full details: Title check

Explanation

The title "fix: await a remote JSON schema before validating" matches the main change. The PR awaits the remote schema fetch in validateJSONSchema.ts before compiling it, caches the resolved schema, and makes jsonSchema.schema optional. The title is specific, uses a conventional fix: prefix, and is one sentence of 8 words. It does not name the JSON field or the payload package, but that detail is not required.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 25dfb24 and 40b390a.

Files selected for processing: 3

  • packages/payload/src/fields/config/types.ts
  • packages/payload/src/fields/validateJSONSchema.spec.ts
  • packages/payload/src/fields/validateJSONSchema.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@pcbeingused333 pcbeingused333 changed the title fix(payload): await a remote JSON schema before validating fix: await a remote JSON schema before validating Nov 8, 2026

This branch has not been deployed

No deployments
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.

JSON field: remote jsonSchema (uri only) is never validated, any value is saved

1 participant