--- title: Common Errors description: Reference for common AI SDK errors and how to resolve them. --- # Common Errors ## `maxTokens` → `maxOutputTokens` ```typescript // ❌ Incorrect const result = await generateText({ model: 'anthropic/claude-opus-4.5', maxTokens: 512, // deprecated: use `maxOutputTokens` instead prompt: 'Write a short story', }); // ✅ Correct const result = await generateText({ model: 'anthropic/claude-opus-4.5', maxOutputTokens: 512, prompt: 'Write a short story', }); ``` ## `maxSteps` → `stopWhen: stepCountIs(n)` ```typescript // ❌ Incorrect const result = await generateText({ model: 'anthropic/claude-opus-4.5', tools: { weather }, maxSteps: 5, // deprecated: use `stopWhen: stepCountIs(n)` instead prompt: 'What is the weather in NYC?', }); // ✅ Correct import { generateText, stepCountIs } from 'ai'; const result = await generateText({ model: 'anthropic/claude-opus-4.5', tools: { weather }, stopWhen: stepCountIs(5), prompt: 'What is the weather in NYC?', }); ``` ## `parameters` → `inputSchema` (in tool definition) ```typescript // ❌ Incorrect const weatherTool = tool({ description: 'Get weather for a location', parameters: z.object({ // deprecated: use `inputSchema` instead location: z.string(), }), execute: async ({ location }) => ({ location, temp: 72 }), }); // ✅ Correct const weatherTool = tool({ description: 'Get weather for a location', inputSchema: z.object({ location: z.string(), }), execute: async ({ location }) => ({ location, temp: 72 }), }); ``` ## `generateObject` → `generateText` with `output` `generateObject` is deprecated. Use `generateText` with the `output` option instead. ```typescript // ❌ Deprecated import { generateObject } from 'ai'; // deprecated: use `generateText` with `output` instead const result = await generateObject({ // deprecated function model: 'anthropic/claude-opus-4.5', schema: z.object({ // deprecated: use `Output.object({ schema })` instead recipe: z.object({ name: z.string(), ingredients: z.array(z.string()), }), }), prompt: 'Generate a recipe for chocolate cake', }); // ✅ Correct import { generateText, Output } from 'ai'; const result = await generateText({ model: 'anthropic/claude-opus-4.5', output: Output.object({ schema: z.object({ recipe: z.object({ name: z.string(), ingredients: z.array(z.string()), }), }), }), prompt: 'Generate a recipe for chocolate cake', }); console.log(result.output); // typed object ``` ## Manual JSON parsing → `generateText` with `output` ```typescript // ❌ Incorrect const result = await generateText({ model: 'anthropic/claude-opus-4.5', prompt: `Extract the user info as JSON: { "name": string, "age": number } Input: John is 25 years old`, }); const parsed = JSON.parse(result.text); // ✅ Correct import { generateText, Output } from 'ai'; const result = await generateText({ model: 'anthropic/claude-opus-4.5', output: Output.object({ schema: z.object({ name: z.string(), age: z.number(), }), }), prompt: 'Extract the user info: John is 25 years old', }); console.log(result.output); // { name: 'John', age: 25 } ``` ## Other `output` options ```typescript // Output.array - for generating arrays of items const result = await generateText({ model: 'anthropic/claude-opus-4.5', output: Output.array({ element: z.object({ city: z.string(), country: z.string(), }), }), prompt: 'List 5 capital cities', }); // Output.choice - for selecting from predefined options const result = await generateText({ model: 'anthropic/claude-opus-4.5', output: Output.choice({ options: ['positive', 'negative', 'neutral'] as const, }), prompt: 'Classify the sentiment: I love this product!', }); // Output.json - for untyped JSON output const result = await generateText({ model: 'anthropic/claude-opus-4.5', output: Output.json(), prompt: 'Return some JSON data', }); ``` ## `toDataStreamResponse` → `toUIMessageStreamResponse` When using `useChat` on the frontend, use `toUIMessageStreamResponse()` instead of `toDataStreamResponse()`. The UI message stream format is designed to work with the chat UI components and handles message state correctly. ```typescript // ❌ Incorrect (when using useChat) const result = streamText({ // config }); return result.toDataStreamResponse(); // deprecated for useChat: use toUIMessageStreamResponse // ✅ Correct const result = streamText({ // config }); return result.toUIMessageStreamResponse(); ``` ## Removed managed input state in `useChat` The `useChat` hook no longer manages input state internally. You must now manage input state manually. ```tsx // ❌ Deprecated import { useChat } from '@ai-sdk/react'; export default function Page() { const { input, // deprecated: manage input state manually with useState handleInputChange, // deprecated: use custom onChange handler handleSubmit, // deprecated: use sendMessage() instead } = useChat({ api: '/api/chat', // deprecated: use `transport: new DefaultChatTransport({ api })` instead }); return (
); } // ✅ Correct import { useChat } from '@ai-sdk/react'; import { DefaultChatTransport } from 'ai'; import { useState } from 'react'; export default function Page() { const [input, setInput] = useState(''); const { sendMessage } = useChat({ transport: new DefaultChatTransport({ api: '/api/chat' }), }); const handleSubmit = e => { e.preventDefault(); sendMessage({ text: input }); setInput(''); }; return ( ); } ``` ## `tool-invocation` → `tool-{toolName}` (typed tool parts) When rendering messages with `useChat`, use the typed tool part names (`tool-{toolName}`) instead of the generic `tool-invocation` type. This provides better type safety and access to tool-specific input/output types. > For end-to-end type-safety, see [Type-Safe Agents](type-safe-agents.md). Typed tool parts also use different property names: - `part.args` → `part.input` - `part.result` → `part.output` ```tsx // ❌ Incorrect - using generic tool-invocation { message.parts.map((part, i) => { switch (part.type) { case 'text': return
{JSON.stringify(part.toolInvocation, null, 2)}
);
}
});
}
// ✅ Correct - using typed tool parts (recommended)
{
message.parts.map(part => {
switch (part.type) {
case 'text':
return part.text;
case 'tool-askForConfirmation':
// handle askForConfirmation tool
break;
case 'tool-getWeatherInformation':
// handle getWeatherInformation tool
break;
}
});
}
// ✅ Alternative - using isToolUIPart as a catch-all
import { isToolUIPart } from 'ai';
{
message.parts.map(part => {
if (part.type === 'text') {
return part.text;
}
if (isToolUIPart(part)) {
// handle any tool part generically
return (