Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vercel AI SDK for building AI-powered applications with streaming, tool calling, and multi-provider support.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/common-errors.md
1---2title: Common Errors3description: Reference for common AI SDK errors and how to resolve them.4---56# Common Errors78## `maxTokens` → `maxOutputTokens`910```typescript11// ❌ Incorrect12const result = await generateText({13model: 'anthropic/claude-opus-4.5',14maxTokens: 512, // deprecated: use `maxOutputTokens` instead15prompt: 'Write a short story',16});1718// ✅ Correct19const result = await generateText({20model: 'anthropic/claude-opus-4.5',21maxOutputTokens: 512,22prompt: 'Write a short story',23});24```2526## `maxSteps` → `stopWhen: isStepCount(n)`2728```typescript29// ❌ Incorrect30const result = await generateText({31model: 'anthropic/claude-opus-4.5',32tools: { weather },33maxSteps: 5, // deprecated: use `stopWhen: isStepCount(n)` instead34prompt: 'What is the weather in NYC?',35});3637// ✅ Correct38import { generateText, isStepCount } from 'ai';3940const result = await generateText({41model: 'anthropic/claude-opus-4.5',42tools: { weather },43stopWhen: isStepCount(5),44prompt: 'What is the weather in NYC?',45});46```4748## `parameters` → `inputSchema` (in tool definition)4950```typescript51// ❌ Incorrect52const weatherTool = tool({53description: 'Get weather for a location',54parameters: z.object({55// deprecated: use `inputSchema` instead56location: z.string(),57}),58execute: async ({ location }) => ({ location, temp: 72 }),59});6061// ✅ Correct62const weatherTool = tool({63description: 'Get weather for a location',64inputSchema: z.object({65location: z.string(),66}),67execute: async ({ location }) => ({ location, temp: 72 }),68});69```7071## `generateObject` → `generateText` with `output`7273`generateObject` is deprecated. Use `generateText` with the `output` option instead.7475```typescript76// ❌ Deprecated77import { generateObject } from 'ai'; // deprecated: use `generateText` with `output` instead7879const result = await generateObject({80// deprecated function81model: 'anthropic/claude-opus-4.5',82schema: z.object({83// deprecated: use `Output.object({ schema })` instead84recipe: z.object({85name: z.string(),86ingredients: z.array(z.string()),87}),88}),89prompt: 'Generate a recipe for chocolate cake',90});9192// ✅ Correct93import { generateText, Output } from 'ai';9495const result = await generateText({96model: 'anthropic/claude-opus-4.5',97output: Output.object({98schema: z.object({99recipe: z.object({100name: z.string(),101ingredients: z.array(z.string()),102}),103}),104}),105prompt: 'Generate a recipe for chocolate cake',106});107108console.log(result.output); // typed object109```110111## Manual JSON parsing → `generateText` with `output`112113```typescript114// ❌ Incorrect115const result = await generateText({116model: 'anthropic/claude-opus-4.5',117prompt: `Extract the user info as JSON: { "name": string, "age": number }118119Input: John is 25 years old`,120});121const parsed = JSON.parse(result.text);122123// ✅ Correct124import { generateText, Output } from 'ai';125126const result = await generateText({127model: 'anthropic/claude-opus-4.5',128output: Output.object({129schema: z.object({130name: z.string(),131age: z.number(),132}),133}),134prompt: 'Extract the user info: John is 25 years old',135});136137console.log(result.output); // { name: 'John', age: 25 }138```139140## Other `output` options141142```typescript143// Output.array - for generating arrays of items144const result = await generateText({145model: 'anthropic/claude-opus-4.5',146output: Output.array({147element: z.object({148city: z.string(),149country: z.string(),150}),151}),152prompt: 'List 5 capital cities',153});154155// Output.choice - for selecting from predefined options156const result = await generateText({157model: 'anthropic/claude-opus-4.5',158output: Output.choice({159options: ['positive', 'negative', 'neutral'] as const,160}),161prompt: 'Classify the sentiment: I love this product!',162});163164// Output.json - for untyped JSON output165const result = await generateText({166model: 'anthropic/claude-opus-4.5',167output: Output.json(),168prompt: 'Return some JSON data',169});170```171172## `toDataStreamResponse` → `createUIMessageStreamResponse`173174When using `useChat` on the frontend, use `createUIMessageStreamResponse()` with `toUIMessageStream()` instead of `toDataStreamResponse()`. The UI message stream format is designed to work with the chat UI components and handles message state correctly.175176```typescript177// ❌ Incorrect (when using useChat)178const result = streamText({179// config180});181182return result.toDataStreamResponse(); // deprecated for useChat: use createUIMessageStreamResponse183184// ✅ Correct185const result = streamText({186// config187});188189return createUIMessageStreamResponse({190stream: toUIMessageStream({ stream: result.stream }),191});192```193194## Removed managed input state in `useChat`195196The `useChat` hook no longer manages input state internally. You must now manage input state manually.197198```tsx199// ❌ Deprecated200import { useChat } from '@ai-sdk/react';201202export default function Page() {203const {204input, // deprecated: manage input state manually with useState205handleInputChange, // deprecated: use custom onChange handler206handleSubmit, // deprecated: use sendMessage() instead207} = useChat({208api: '/api/chat', // deprecated: use `transport: new DefaultChatTransport({ api })` instead209});210211return (212<form onSubmit={handleSubmit}>213<input value={input} onChange={handleInputChange} />214<button type="submit">Send</button>215</form>216);217}218219// ✅ Correct220import { useChat } from '@ai-sdk/react';221import { DefaultChatTransport } from 'ai';222import { useState } from 'react';223224export default function Page() {225const [input, setInput] = useState('');226const { sendMessage } = useChat({227transport: new DefaultChatTransport({ api: '/api/chat' }),228});229230const handleSubmit = e => {231e.preventDefault();232sendMessage({ text: input });233setInput('');234};235236return (237<form onSubmit={handleSubmit}>238<input value={input} onChange={e => setInput(e.target.value)} />239<button type="submit">Send</button>240</form>241);242}243```244245## `tool-invocation` → `tool-{toolName}` (typed tool parts)246247When 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.248249> For end-to-end type-safety, see [Type-Safe Agents](type-safe-agents.md).250251Typed tool parts also use different property names:252253- `part.args` → `part.input`254- `part.result` → `part.output`255256```tsx257// ❌ Incorrect - using generic tool-invocation258{259message.parts.map((part, i) => {260switch (part.type) {261case 'text':262return <div key={`${message.id}-${i}`}>{part.text}</div>;263case 'tool-invocation': // deprecated: use typed tool parts instead264return (265<pre key={`${message.id}-${i}`}>266{JSON.stringify(part.toolInvocation, null, 2)}267</pre>268);269}270});271}272273// ✅ Correct - using typed tool parts (recommended)274{275message.parts.map(part => {276switch (part.type) {277case 'text':278return part.text;279case 'tool-askForConfirmation':280// handle askForConfirmation tool281break;282case 'tool-getWeatherInformation':283// handle getWeatherInformation tool284break;285}286});287}288289// ✅ Alternative - using isToolUIPart as a catch-all290import { isToolUIPart } from 'ai';291292{293message.parts.map(part => {294if (part.type === 'text') {295return part.text;296}297if (isToolUIPart(part)) {298// handle any tool part generically299return (300<div key={part.toolCallId}>301{part.toolName}: {part.state}302</div>303);304}305});306}307```308309## `useChat` state-dependent property access310311Tool part properties are only available in certain states. TypeScript will error if you access them without checking state first.312313```tsx314// ❌ Incorrect - input may be undefined during streaming315// TS18048: 'part.input' is possibly 'undefined'316if (part.type === 'tool-getWeather') {317const location = part.input.location;318}319320// ✅ Correct - check for input-available or output-available321if (322part.type === 'tool-getWeather' &&323(part.state === 'input-available' || part.state === 'output-available')324) {325const location = part.input.location;326}327328// ❌ Incorrect - output is only available after execution329// TS18048: 'part.output' is possibly 'undefined'330if (part.type === 'tool-getWeather') {331const weather = part.output;332}333334// ✅ Correct - check for output-available335if (part.type === 'tool-getWeather' && part.state === 'output-available') {336const location = part.input.location;337const weather = part.output;338}339```340341## `part.toolInvocation.args` → `part.input`342343```tsx344// ❌ Incorrect345if (part.type === 'tool-invocation') {346// deprecated: use `part.input` on typed tool parts instead347const location = part.toolInvocation.args.location;348}349350// ✅ Correct351if (352part.type === 'tool-getWeather' &&353(part.state === 'input-available' || part.state === 'output-available')354) {355const location = part.input.location;356}357```358359## `part.toolInvocation.result` → `part.output`360361```tsx362// ❌ Incorrect363if (part.type === 'tool-invocation') {364// deprecated: use `part.output` on typed tool parts instead365const weather = part.toolInvocation.result;366}367368// ✅ Correct369if (part.type === 'tool-getWeather' && part.state === 'output-available') {370const weather = part.output;371}372```373374## `part.toolInvocation.toolCallId` → `part.toolCallId`375376```tsx377// ❌ Incorrect378if (part.type === 'tool-invocation') {379// deprecated: use `part.toolCallId` on typed tool parts instead380const id = part.toolInvocation.toolCallId;381}382383// ✅ Correct384if (part.type === 'tool-getWeather') {385const id = part.toolCallId;386}387```388389## Tool invocation states renamed390391```tsx392// ❌ Incorrect393switch (part.toolInvocation.state) {394case 'partial-call': // deprecated: use `input-streaming` instead395return <div>Loading...</div>;396case 'call': // deprecated: use `input-available` instead397return <div>Executing...</div>;398case 'result': // deprecated: use `output-available` instead399return <div>Done</div>;400}401402// ✅ Correct403switch (part.state) {404case 'input-streaming':405return <div>Loading...</div>;406case 'input-available':407return <div>Executing...</div>;408case 'output-available':409return <div>Done</div>;410}411```412413## `addToolResult` → `addToolOutput`414415```tsx416// ❌ Incorrect417addToolResult({418// deprecated: use `addToolOutput` instead419toolCallId: part.toolInvocation.toolCallId,420result: 'Yes, confirmed.', // deprecated: use `output` instead421});422423// ✅ Correct424addToolOutput({425tool: 'askForConfirmation',426toolCallId: part.toolCallId,427output: 'Yes, confirmed.',428});429```430431## `messages` → `uiMessages` in `createAgentUIStreamResponse`432433```typescript434// ❌ Incorrect435return createAgentUIStreamResponse({436agent: myAgent,437messages, // incorrect: use `uiMessages` instead438});439440// ✅ Correct441return createAgentUIStreamResponse({442agent: myAgent,443uiMessages: messages,444});445```446