vercel/ai · error
Tool call ${part.toolCallId} not found.
Error message
Tool call ${part.toolCallId} not found. What it means
While converting LanguageModelV* content into step content, a 'tool-result' (or related) part references a toolCallId that is not present among the tool calls emitted earlier in the same response. convertLanguageModelContent throws a plain Error because a tool result without its call is an inconsistent model stream. This typically indicates a provider/stream bug or corrupted stream data.
Source
Thrown at packages/ai/src/generate-text/convert-language-model-content.ts:71
part.data.type === 'data'
? part.data.data
: part.data.url.toString(),
mediaType: part.mediaType,
}),
...(part.providerMetadata != null
? { providerMetadata: part.providerMetadata }
: {}),
});
break;
}
case 'tool-call': {
const toolCall = toolCalls.find(
toolCall => toolCall.toolCallId === part.toolCallId,
);
if (toolCall == null) {
throw new Error(`Tool call ${part.toolCallId} not found.`);
}
contentParts.push(toolCall);
break;
}
case 'tool-result': {
const toolCall = toolCalls.find(
toolCall => toolCall.toolCallId === part.toolCallId,
);
// Handle deferred results for provider-executed tools (e.g., programmatic tool calling).
// When a server tool (like code_execution) triggers a client tool, the server tool's
// result may be deferred to a later turn. In this case, there's no matching tool-call
// in the current response.
if (toolCall == null) {
const tool = getOwn(tools, part.toolName);
const supportsDeferredResults =View on GitHub (pinned to 69428b1f8b)
Solutions
- Fix the mock/custom provider so every tool result is preceded by a tool-call part with the same toolCallId
- Verify toolCallId generation matches between call and result parts in custom providers
- Update the provider package to the latest version in case of a known stream bug
- Capture the raw stream to identify which part references the missing id
Example fix
// before
toolResults: [{ toolCallId: 'call_1', result: 42 }] // no matching toolCall
// after
toolCalls: [{ toolCallId: 'call_1', toolName: 'get', input: {} }],
toolResults: [{ toolCallId: 'call_1', result: 42 }] Defensive patterns
Strategy: validation
Validate before calling
const callIds = new Set(content.filter(p => p.type === 'tool-call').map(p => p.toolCallId));
const orphan = content.filter(p => p.type === 'tool-result' && !callIds.has(p.toolCallId));
if (orphan.length) throw new Error('tool results without matching calls: ' + orphan.map(o => o.toolCallId)); Type guard
function hasMatchingToolCalls(content: { type: string; toolCallId?: string }[]): boolean {
const ids = new Set(content.filter(p => p.type === 'tool-call').map(p => p.toolCallId!));
return content.filter(p => p.type === 'tool-result').every(p => ids.has(p.toolCallId!));
} Try / catch
try {
return await generateText({ model, prompt });
} catch (e) {
if (e instanceof Error && /Tool call .* not found/.test(e.message)) {
console.error('stream inconsistency; check provider/mock content order');
}
throw e;
} Prevention
- In mock providers, always emit tool-call parts before their results
- Keep provider packages up to date
- Verify toolCallId consistency when synthesizing stream chunks
When it happens
Trigger: A provider stream emits a tool-result/tool-approval part with a toolCallId never seen in a preceding tool-call part; custom mock streams in tests emit results before/outside their calls; provider sends duplicated or mismatched call ids after streaming interruptions.
Common situations: Building mock providers with hand-written content arrays that omit the tool-call part; provider API changes or beta endpoints with inconsistent ids; partial stream capture where the tool-call chunk was lost.
Related errors
- 'element streams in no-schema mode' functionality not suppor
- 'element streams in object mode' functionality not supported
- Unsupported chunk type: ${_exhaustiveCheck}
- 'element streams in enum mode' functionality not supported.
- Unsupported chunk type: ${_exhaustiveCheck}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/a1a8b2b0d6bcd5c8.
Report an issue: GitHub.