vercel/ai · error · UnsupportedFunctionalityError
Google schema conversion does not support recursive JSON Sch
Error message
Google schema conversion does not support recursive JSON Schema references.
What it means
Google's OpenAPI-compatible schema format (used for tool/function calling and structured output) cannot express recursive $ref cycles. During conversion, if a JSON Schema `$ref` is encountered while that same reference is already being resolved (a cycle), the converter throws instead of emitting an invalid recursive schema.
Source
Thrown at packages/google/src/convert-json-schema-to-openapi-schema.ts:219
function convertJSONSchemaReference({
jsonSchema,
reference,
isRoot,
referenceContext,
}: {
jsonSchema: JSONSchema7;
reference: string;
isRoot: boolean;
referenceContext: ReferenceContext;
}): unknown {
const { definition, referenceKey } = getReferencedDefinition(
reference,
referenceContext,
);
if (referenceContext.resolvingReferences.has(referenceKey)) {
throw new UnsupportedFunctionalityError({
functionality: `${recursiveReferenceFunctionalityPrefix} ${reference}`,
message:
'Google schema conversion does not support recursive JSON Schema references.',
});
}
const resolvingReferences = new Set(referenceContext.resolvingReferences);
resolvingReferences.add(referenceKey);
// Inline references instead of emitting Google's `ref` / `defs` fields.
// Those fields are supported by Vertex AI's Schema representation but are
// rejected by the Gemini Developer API representation used by this shared
// converter.
const { $ref: _reference, ...siblingSchema } = jsonSchema;
const resolvedSchema =
typeof definition === 'boolean'
? definition
? siblingSchemaView on GitHub (pinned to 69428b1f8b)
Solutions
- Flatten the recursion: replace recursive definitions with a bounded depth (e.g. 3-4 explicitly nested levels) or an array-of-strings representation.
- Use a provider that supports recursive schemas (e.g. OpenAI) if recursion is essential.
- Serialize recursive data yourself (e.g. pass as a string field with instructions) instead of typed schema recursion.
Example fix
// before
const nodeSchema = z.lazy(() => z.object({ name: z.string(), children: z.array(nodeSchema) }));
// after
const nodeSchema = z.object({ name: z.string(), children: z.array(z.object({ name: z.string() })) }); // bounded depth Defensive patterns
Strategy: validation
Validate before calling
function hasRecursiveRef(schema, seen = new Set()) {
if (schema && typeof schema === 'object') {
if (typeof schema.$ref === 'string') {
const key = schema.$ref.split('/').pop();
if (seen.has(key)) return true;
seen.add(key);
}
return Object.values(schema).some(v => hasRecursiveRef(v, new Set(seen)));
}
return false;
}
// if (hasRecursiveRef(jsonSchema)) throw / flatten before calling Google Type guard
function isNonRecursiveSchema(schema, rootDefs = schema.$defs ?? schema.definitions ?? {}) {
return !Object.keys(rootDefs).some(def => JSON.stringify(schema).includes(`#/$defs/${def}`) && JSON.stringify(rootDefs[def]).includes(`$defs/${def}`));
} Try / catch
try {
await generateText({ model: google('gemini-2.0-flash'), tools });
} catch (e) {
if (e?.message?.includes('recursive JSON Schema references')) {
// fall back to flattened schema or another provider
} else throw e;
} Prevention
- Avoid z.lazy() / self-referencing types in tool and structured-output schemas for Google.
- Bound recursion depth explicitly in your domain types.
- Test schema conversion in CI with the target provider before deploying.
When it happens
Trigger: Passing a zod schema converted via z.toJSONSchema (or a hand-written JSON Schema) that contains a self-referencing definition, e.g. a `Node` type with `children: Node[]`, into `generateText`/`generateObject` with a Google model. Detected by the `resolvingReferences` set in convertJSONSchemaReference.
Common situations: Tree/graph-shaped tool inputs (JSON, org charts, ASTs); recursive zod schemas using z.lazy(); migrating tool schemas from OpenAI (which supports recursion) to Google.
Related errors
- Google schema conversion only supports references to direct
- Google does not support this JSON Schema enum. Enum values m
- Recursive reference detected at ${refs.currentPath.join('/')
- Could not convert regex pattern at ${refs.currentPath.join('
- Model tried to call unavailable tool '${toolName}'. No tools
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/233c720a9543593b.
Report an issue: GitHub.