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` → `toUIMessageStreamResponse`173174When 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.175176```typescript177// ❌ Incorrect (when using useChat)178const result = streamText({179// config180});181182return result.toDataStreamResponse(); // deprecated for useChat: use toUIMessageStreamResponse183184// ✅ Correct185const result = streamText({186// config187});188189return result.toUIMessageStreamResponse();190```191192## Removed managed input state in `useChat`193194The `useChat` hook no longer manages input state internally. You must now manage input state manually.195196```tsx197// ❌ Deprecated198import { useChat } from '@ai-sdk/react';199200export default function Page() {201const {202input, // deprecated: manage input state manually with useState203handleInputChange, // deprecated: use custom onChange handler204handleSubmit, // deprecated: use sendMessage() instead205} = useChat({206api: '/api/chat', // deprecated: use `transport: new DefaultChatTransport({ api })` instead207});208209return (210<form onSubmit={handleSubmit}>211<input value={input} onChange={handleInputChange} />212<button type="submit">Send</button>213</form>214);215}216217// ✅ Correct218import { useChat } from '@ai-sdk/react';219import { DefaultChatTransport } from 'ai';220import { useState } from 'react';221222export default function Page() {223const [input, setInput] = useState('');224const { sendMessage } = useChat({225transport: new DefaultChatTransport({ api: '/api/chat' }),226});227228const handleSubmit = e => {229e.preventDefault();230sendMessage({ text: input });231setInput('');232};233234return (235<form onSubmit={handleSubmit}>236<input value={input} onChange={e => setInput(e.target.value)} />237<button type="submit">Send</button>238</form>239);240}241```242243## `tool-invocation` → `tool-{toolName}` (typed tool parts)244245When 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.246247> For end-to-end type-safety, see [Type-Safe Agents](type-safe-agents.md).248249Typed tool parts also use different property names:250251- `part.args` → `part.input`252- `part.result` → `part.output`253254```tsx255// ❌ Incorrect - using generic tool-invocation256{257message.parts.map((part, i) => {258switch (part.type) {259case 'text':260return <div key={`${message.id}-${i}`}>{part.text}</div>;261case 'tool-invocation': // deprecated: use typed tool parts instead262return (263<pre key={`${message.id}-${i}`}>264{JSON.stringify(part.toolInvocation, null, 2)}265</pre>266);267}268});269}270271// ✅ Correct - using typed tool parts (recommended)272{273message.parts.map(part => {274switch (part.type) {275case 'text':276return part.text;277case 'tool-askForConfirmation':278// handle askForConfirmation tool279break;280case 'tool-getWeatherInformation':281// handle getWeatherInformation tool282break;283}284});285}286287// ✅ Alternative - using isToolUIPart as a catch-all288import { isToolUIPart } from 'ai';289290{291message.parts.map(part => {292if (part.type === 'text') {293return part.text;294}295if (isToolUIPart(part)) {296// handle any tool part generically297return (298<div key={part.toolCallId}>299{part.toolName}: {part.state}300</div>301);302}303});304}305```306307## `useChat` state-dependent property access308309Tool part properties are only available in certain states. TypeScript will error if you access them without checking state first.310311```tsx312// ❌ Incorrect - input may be undefined during streaming313// TS18048: 'part.input' is possibly 'undefined'314if (part.type === 'tool-getWeather') {315const location = part.input.location;316}317318// ✅ Correct - check for input-available or output-available319if (320part.type === 'tool-getWeather' &&321(part.state === 'input-available' || part.state === 'output-available')322) {323const location = part.input.location;324}325326// ❌ Incorrect - output is only available after execution327// TS18048: 'part.output' is possibly 'undefined'328if (part.type === 'tool-getWeather') {329const weather = part.output;330}331332// ✅ Correct - check for output-available333if (part.type === 'tool-getWeather' && part.state === 'output-available') {334const location = part.input.location;335const weather = part.output;336}337```338339## `part.toolInvocation.args` → `part.input`340341```tsx342// ❌ Incorrect343if (part.type === 'tool-invocation') {344// deprecated: use `part.input` on typed tool parts instead345const location = part.toolInvocation.args.location;346}347348// ✅ Correct349if (350part.type === 'tool-getWeather' &&351(part.state === 'input-available' || part.state === 'output-available')352) {353const location = part.input.location;354}355```356357## `part.toolInvocation.result` → `part.output`358359```tsx360// ❌ Incorrect361if (part.type === 'tool-invocation') {362// deprecated: use `part.output` on typed tool parts instead363const weather = part.toolInvocation.result;364}365366// ✅ Correct367if (part.type === 'tool-getWeather' && part.state === 'output-available') {368const weather = part.output;369}370```371372## `part.toolInvocation.toolCallId` → `part.toolCallId`373374```tsx375// ❌ Incorrect376if (part.type === 'tool-invocation') {377// deprecated: use `part.toolCallId` on typed tool parts instead378const id = part.toolInvocation.toolCallId;379}380381// ✅ Correct382if (part.type === 'tool-getWeather') {383const id = part.toolCallId;384}385```386387## Tool invocation states renamed388389```tsx390// ❌ Incorrect391switch (part.toolInvocation.state) {392case 'partial-call': // deprecated: use `input-streaming` instead393return <div>Loading...</div>;394case 'call': // deprecated: use `input-available` instead395return <div>Executing...</div>;396case 'result': // deprecated: use `output-available` instead397return <div>Done</div>;398}399400// ✅ Correct401switch (part.state) {402case 'input-streaming':403return <div>Loading...</div>;404case 'input-available':405return <div>Executing...</div>;406case 'output-available':407return <div>Done</div>;408}409```410411## `addToolResult` → `addToolOutput`412413```tsx414// ❌ Incorrect415addToolResult({416// deprecated: use `addToolOutput` instead417toolCallId: part.toolInvocation.toolCallId,418result: 'Yes, confirmed.', // deprecated: use `output` instead419});420421// ✅ Correct422addToolOutput({423tool: 'askForConfirmation',424toolCallId: part.toolCallId,425output: 'Yes, confirmed.',426});427```428429## `messages` → `uiMessages` in `createAgentUIStreamResponse`430431```typescript432// ❌ Incorrect433return createAgentUIStreamResponse({434agent: myAgent,435messages, // incorrect: use `uiMessages` instead436});437438// ✅ Correct439return createAgentUIStreamResponse({440agent: myAgent,441uiMessages: messages,442});443```444