From 734091f6f2ff30f992ca46ebe25f8c0c5dc88eea Mon Sep 17 00:00:00 2001 From: can1357 Date: Fri, 15 May 2026 18:13:15 +0200 Subject: [PATCH] fix(ai/schema): fail validation when primitive ref recursion exceeds cap Primitive $ref recursion now emits a validation issue when the depth cap is exceeded instead of returning true. This preserves termination without accepting invalid values at the end of a long ref chain. --- packages/ai/src/utils/schema/json-schema-validator.ts | 5 ++++- packages/ai/test/schema-strict-mode.test.ts | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/ai/src/utils/schema/json-schema-validator.ts b/packages/ai/src/utils/schema/json-schema-validator.ts index c6bf82dec..6a55575ea 100644 --- a/packages/ai/src/utils/schema/json-schema-validator.ts +++ b/packages/ai/src/utils/schema/json-schema-validator.ts @@ -153,7 +153,10 @@ function validateSchemaNode( if (ctx.seenPairs.has(pairKey)) return true; ctx.seenPairs.add(pairKey); } else { - if (ctx.refDepth >= MAX_REF_DEPTH) return true; + if (ctx.refDepth >= MAX_REF_DEPTH) { + pushIssue(issues, path, "reference depth exceeded", { keyword: "$ref" }); + return false; + } ctx.refDepth += 1; } const ok = validateSchemaNode(resolved, value, path, ctx, issues); diff --git a/packages/ai/test/schema-strict-mode.test.ts b/packages/ai/test/schema-strict-mode.test.ts index 9bf053b3a..aca4c9485 100644 --- a/packages/ai/test/schema-strict-mode.test.ts +++ b/packages/ai/test/schema-strict-mode.test.ts @@ -583,6 +583,17 @@ describe("json-schema validator unsupported-keyword regressions", () => { expect(isJsonSchemaValueValid(schema, { name: "root", child: { name: 123 } })).toBe(false); expect(isJsonSchemaValueValid(schema, { name: "root", child: { child: { name: "x" } } })).toBe(false); }); + + it("fails primitive $ref chains that exceed the recursion cap instead of accepting invalid values", () => { + const definitions: Record = {}; + for (let i = 0; i < 66; i += 1) { + definitions[`A${i}`] = { $ref: `#/definitions/A${i + 1}` }; + } + definitions.A66 = { type: "number" }; + + const schema = { $ref: "#/definitions/A0", definitions }; + expect(isJsonSchemaValueValid(schema, "not-a-number")).toBe(false); + }); }); describe("meta-validator conditional keywords", () => {