Repository navigation
Precompiled validators miss sub-schemas under patternProperties and additionalProperties #5373
Description
Prerequisites
- I have searched the existing issues
- I understand that providing a SSCCE example is tremendously useful to the maintainers.
- I have read the documentation
- Ideally, I'm providing a sample JSFiddle, Codesandbox.io or preferably a shared playground link demonstrating the issue.
What theme are you using?
validator-ajv8
Version
v7 branch (also affects @rjsf/validator-ata)
Current Behavior
A precompiled validator throws No precompiled validator function was found for the given schema when a oneOf/anyOf is reachable only through a patternProperties or additionalProperties value.
schemaParser() collects the sub-schemas that isValid() will be called with, and compileSchemaValidators()/compileSchemaValidatorsCode() precompile a validator for each of them by hash. parseSchema() only recurses into a schema's properties and non-tuple items, so the values of patternProperties and additionalProperties are never parsed on their own. At runtime, stubExistingAdditionalProperties() gives each extra key in the form data its patternProperties/additionalProperties schema, and computing that key's defaults or rendering its MultiSchemaField calls isValid() on the options, whose hashes are missing from the precompiled map.
Found by the code review of #5371 (the #5338 fix), which only covers a patternProperties entry that matches a named property, because that one is merged into the property.
Expected Behavior
Every sub-schema the form can validate against has a precompiled function, including those under patternProperties and additionalProperties.
Steps To Reproduce
import type { RJSFSchema } from '@rjsf/utils';
import { getDefaultFormState, schemaParser } from '@rjsf/utils';
import { compileSchemaValidatorsCode } from '@rjsf/validator-ajv8/compileSchemaValidators';
import { createPrecompiledValidator } from '@rjsf/validator-ajv8';
const choice: RJSFSchema = { oneOf: [{ const: 'a' }, { const: 'b' }] };
// Either one reproduces it
const rootSchema: RJSFSchema = { type: 'object', patternProperties: { '^x_': choice } };
// const rootSchema: RJSFSchema = { type: 'object', additionalProperties: choice };
// false: the options were never parsed
Object.values(schemaParser(rootSchema)).some((s) => s.const === 'a');
const validator = createPrecompiledValidator(loadModule(compileSchemaValidatorsCode(rootSchema)), rootSchema);
// Error: No precompiled validator function was found for the given schema for "-4c020a92"
getDefaultFormState({ validator }, { schema: rootSchema, rootSchema, formData: { x_1: 'b' } });(loadModule evaluates the generated module code, as test/harness/compileSuperSchema.ts#evalValidatorCode does.)
Both variants were confirmed against the fix-5338 branch.
Environment
- **OS**: macOS (Darwin 25.6.0)
- **Node**: 24.21.0Anything else?
A likely fix is for parseSchema() to also recurse into each patternProperties value and an object-valued additionalProperties, the way it does for properties; recurseList already skips schemas it has seen. The same probably applies to tuple items and additionalItems, which it also skips today.
Activity
heath-freenome commentedon Oct 3, 2026
Fixed by #5371, in
36aae2838— dated three days after this was filed, which is why it reproduced againstfix-5338at the time.That commit rewrote the parser's recursion into
parseValueSchemas(), which walksproperties,additionalProperties, every combination ofpatternProperties, every position of a tupleitems, andadditionalItems. So the "same probably applies to tupleitemsandadditionalItems" note is covered too.patternPropertiesisn't walked as the patterns themselves but as{ allOf: [...matching] }for each subset of them, because a form renders a key with the merge of every pattern it matches and a parse has no form data to say which key matches which. There are2^n - 1subsets, so a schema with more than 16patternPropertiesis now reported with a message saying why rather than parsed for minutes.Verification
I ran this issue's repro at the
v7base (320152a9f) and at the PR head (330a8eb53), swapping only the four changed@rjsf/utilssource files so nothing else varied.v7basepatternProperties: { '^x_': choice }getDefaultFormState()throwsNo precompiled validator function was found for the given schema for "-4c020a92"{"x_1":"b"}additionalProperties: choice{"x_1":"b"}, scoring returns option1One correction to the report: the
additionalPropertiesvariant does not throw throughgetDefaultFormState()at the base — that path returns{"x_1":"b"}without scoring the options. It throws one step later, whereMultiSchemaFieldwould: retrieving the stubbedx_1and scoring its retrieved options raises the identical error on the identical hash. The sub-schemas are missing from the compiled map either way, which is what the issue is about; only the triggering call differs.Since
schemaParser()lives in@rjsf/utils,@rjsf/validator-atais fixed by the same change.Locked in by two tests in
packages/utils/test/parser/schemaParser.test.ts—parses the options of the additionalProperties and patternProperties a form renders extra keys with, which is this issue's schema almost verbatim, andparses the options of every position of a tuple items and of its additionalItems.heath-freenome commentedon Oct 7, 2026
Fixed in the upcoming v7 release