support derived/unknown zod schema in generateObject.schema
Description
Hello!
I'm migrating from zod-gpt to use ai instead. It's working in every single case, except one where I do this:
const functionCall = functionCalls[prompt.functionCall];
const { object, usage } = await generateObject({
model: openai(prompt.model),
schema: functionCall,
prompt: content,
});
(reproduction below)
It gives me the following error:
No overload matches this call.
The last overload gave the following error.
Object literal may only specify known properties, and 'schema' does not exist in type 'Omit<CallSettings, "stopSequences"> & Prompt & { output: "no-schema"; model: LanguageModelV1; mode?: "json" | undefined; experimental_telemetry?: TelemetrySettings | undefined; experimental_providerMetadata?: LanguageModelV1ProviderMetadata | undefined; _internal?: { ...; } | undefined; }'.ts(2769)
What do I need to do to solve this?
Code example
import { createOpenAI } from "@ai-sdk/openai";
import { generateObject } from "ai";
import { z } from "zod";
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY!,
compatibility: "strict", // strict mode, enable when using the OpenAI API
});
export const dynamic = "force-dynamic";
type FunctionCall = "test1" | "test2";
const test1 = z.object({
type: z.literal("test1").default("test1"),
test: z.string().describe("test1"),
});
const test2 = z.object({
type: z.literal("test2").default("test2"),
test: z.string().describe("test2"),
});
const functionCalls = {
test1,
test2,
} satisfies Record<FunctionCall, z.ZodTypeAny>;
export const GET = async () => {
const prompt: {
functionCall: FunctionCall;
model: string;
} = {
functionCall: "test1",
model: "gpt-4o-mini",
};
const content = "test";
const functionCall = functionCalls[prompt.functionCall];
const { object, usage } = await generateObject({
model: openai(prompt.model),
schema: functionCall,
prompt: content,
});
return Response.json({ object, usage });
};
Additional context
I've also tried as const Instead of satisfies and not having anything at all. Same issue
"ai": "3.4.9",
Try updating your @ai-sdk/openai package - mine seemed to be stuck at 0.0.36 and this resolved it for me.
Thanks for the comment, I'm on 0.0.66 though
In the code snippet, the functionCall variable you are passing into generateObject appears to be a z.Object. The versions of the overloaded generateObject function whose argument has a schema property, requires that it be a schema type (e.g. z.Schema<ELEMENT, z.ZodTypeDef, any> | Schema<ELEMENT>). I think that's the reason your call doesn't match any of the overloads.
The error message comes from the attempt to match the one declared last in the library, which doesn't have a schema property on its argument at all.
@jonriegel thanks for the comment. I looked into the definition files after your reply and I see it too. But I don't know how to translate it to code. Any suggestions?
I ran into a similar issue caused by generateObject's ordering of overload definitions.
Eventually found a workaround using the Overloads type from this SO answer. https://stackoverflow.com/a/64107995 Copy-pasted below:
type Overloads<T> =
T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2;
(...args: infer A3): infer R3; (...args: infer A4): infer R4
} ? [
(...args: A1) => R1, (...args: A2) => R2,
(...args: A3) => R3, (...args: A4) => R4
] : T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2;
(...args: infer A3): infer R3
} ? [
(...args: A1) => R1, (...args: A2) => R2,
(...args: A3) => R3
] : T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2
} ? [
(...args: A1) => R1, (...args: A2) => R2
] : T extends {
(...args: infer A1): infer R1
} ? [
(...args: A1) => R1
] : any
@benjick for your example, looks like the error can be removed by defining the argument for generateObject as an outside variable typed with Parameters and Overloads. Code:
const functionCall = functionCalls[prompt.functionCall];
const params: Parameters<Overloads<typeof generateObject>[number]>[0] = {
model: openai(prompt.model),
schema: functionCall,
prompt: content,
};
const { object, usage } = await generateObject(params);
Now it matches the correct overload based on the properties of params. the 'schema' does not exist in type error only shows up again if you explicitly set output: 'no-schema', as we'd expect.
The issue here is that generateObject (in with object output, the overload error is a red herring) expects a fixed schema for correct output inference, and you pass a schema with |:
This fails to infer the type of the result. I'll think about how to pass through union types; ideally it should be possible.
I'm having the exact same issue here with the overload warnings. Even though the code actually works fine
import type { SchemaName } from "@/types/schema-types";
import { recipeSchema } from "./recipeSchema";
import { articleSchema } from "./quizSchema";
export const schemas = {
recipe: recipeSchema,
article: articleSchema,
} as const;
and then I try to use it here
import { schemas } from "@/app/schemas/schemas";
import type { SchemaName } from "@/types/schema-types";
import { google } from "@ai-sdk/google";
import { generateObject, zodSchema } from "ai";
import { NextResponse } from "next/server";
// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
export async function POST(req: Request) {
const request = await req.json();
const schemaName = request.schemaName as SchemaName;
const schema = schemas[schemaName];
if (!schema) {
return new NextResponse("Schema not found", { status: 404 });
}
if (!request.prompt) {
return new NextResponse("Prompt is required", { status: 400 });
}
try {
const { object } = await generateObject({
model: google("gemini-2.0-flash-001"),
prompt: request.prompt,
schema: zodSchema(schema),
});
return new NextResponse(JSON.stringify(object));
} catch (error) {
console.log("error generated is", error);
return new NextResponse("Error generated", { status: 500 });
}
}
Any plans to fix this on library end? I'm also having this and I really would like to avoid workarounds here :)
👍
I think generateObject is unusable with this right now...
Using the code verbatim with documentation also cause some of this type error.
https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-object#example-generate-an-array-using-a-schema
Overload 1 of 3, '(options: Omit<CallSettings, "stopSequences"> & Prompt & { output?: "object" | undefined; model: LanguageModelV1; schema: ZodType<unknown, ZodTypeDef, any> | Schema<...>; ... 8 more ...; _internal?: { ...; } | undefined; }): StreamObjectResult<...>', gave the following error.
Type 'ZodObject<{ recipe: ZodObject<{ name: ZodString; ingredients: ZodArray<ZodString>; steps: ZodArray<ZodString>; }, $strip>; }, $strip>' is not assignable to type 'ZodType<unknown, ZodTypeDef, any> | Schema<unknown>'.
Type 'ZodObject<{ recipe: ZodObject<{ name: ZodString; ingredients: ZodArray<ZodString>; steps: ZodArray<ZodString>; }, $strip>; }, $strip>' is missing the following properties from type 'ZodType<unknown, ZodTypeDef, any>': _type, _parse, _getType, _getOrReturnCtx, and 7 more.
Overload 2 of 3, '(options: Omit<CallSettings, "stopSequences"> & Prompt & { output: "array"; model: LanguageModelV1; schema: ZodType<unknown, ZodTypeDef, any> | Schema<...>; ... 8 more ...; _internal?: { ...; } | undefined; }): StreamObjectResult<...>', gave the following error.
Type 'ZodObject<{ recipe: ZodObject<{ name: ZodString; ingredients: ZodArray<ZodString>; steps: ZodArray<ZodString>; }, $strip>; }, $strip>' is not assignable to type 'ZodType<unknown, ZodTypeDef, any> | Schema<unknown>'.
Type 'ZodObject<{ recipe: ZodObject<{ name: ZodString; ingredients: ZodArray<ZodString>; steps: ZodArray<ZodString>; }, $strip>; }, $strip>' is missing the following properties from type 'ZodType<unknown, ZodTypeDef, any>': _type, _parse, _getType, _getOrReturnCtx, and 7 more.
Overload 3 of 3, '(options: Omit<CallSettings, "stopSequences"> & Prompt & { output: "no-schema"; model: LanguageModelV1; mode?: "json" | undefined; experimental_telemetry?: TelemetrySettings | undefined; ... 4 more ...; _internal?: { ...; } | undefined; }): StreamObjectResult<...>', gave the following error.
Object literal may only specify known properties, and 'schema' does not exist in type 'Omit<CallSettings, "stopSequences"> & Prompt & { output: "no-schema"; model: LanguageModelV1; mode?: "json" | undefined; experimental_telemetry?: TelemetrySettings | undefined; ... 4 more ...; _internal?: { ...; } | undefined; }'.
27 schema: z.object({
Downgrading zod from v4 to v3 fixed the issue.
"zod": "^3.25.28"
seems to be an issue with zod v4
instead of downgrading to v3 for zod
✅ you could do
import { z } from "zod/v3";
❌ instead of
import { z } from "zod";
i don;t w
seems to be an issue with zod v4
instead of downgrading to v3 for zod
✅ you could do
import { z } from "zod/v3"; ❌ instead of
import { z } from "zod";
This worked. Thanks