vercel/ai · error · ToolCallRepairError
Error repairing tool call: ${getErrorMessage(cause)}
Error message
Error repairing tool call: ${getErrorMessage(cause)} What it means
ToolCallRepairError wraps a failure that happened inside `experimental_repairToolCall` while trying to fix a broken tool call (e.g. malformed JSON). The original parse error is preserved as `originalError` and the repair failure as `cause`. It signals the repair path itself threw, not the original defect.
Source
Thrown at packages/ai/src/generate-text/parse-tool-call.ts:79
}
let repairedToolCall: LanguageModelV4ToolCall | null = null;
try {
repairedToolCall = await repairToolCall({
toolCall,
tools,
inputSchema: async ({ toolName }) => {
const inputSchema = getOwn(tools, toolName)?.inputSchema;
return await asSchema(inputSchema).jsonSchema;
},
instructions,
system: instructions,
messages,
error,
});
} catch (repairError) {
throw new ToolCallRepairError({
cause: repairError,
originalError: error,
});
}
// no repaired tool call returned
if (repairedToolCall == null) {
throw error;
}
return await refineParsedToolCallInput({
toolCall: await doParseToolCall({ toolCall: repairedToolCall, tools }),
refineToolInput,
});
}
} catch (error) {
// use parsed input when possible
const parsedInput = await safeParseJSON({ text: toolCall.input });View on GitHub (pinned to 69428b1f8b)
Solutions
- Inspect `error.cause` for the real reason the repair function failed and fix that (API key, model availability, prompt).
- Make the repair function defensive: wrap its body in try/catch and return the original tool call or null instead of throwing.
- Validate that the model used for repair supports tool calling and is correctly configured.
Example fix
// before
experimental_repairToolCall: async ({ toolCall, error }) => {
const fixed = await repairModel(toolCall); // may throw
return fixed;
}
// after
experimental_repairToolCall: async ({ toolCall, error }) => {
try {
return await repairModel(toolCall);
} catch (e) {
return null; // give up gracefully instead of throwing
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if (experimental_repairToolCall && typeof experimental_repairToolCall !== 'function') {
throw new Error('experimental_repairToolCall must be a function');
} Try / catch
try {
await generateText({ model, prompt, tools, experimental_repairToolCall });
} catch (e) {
if (ToolCallRepairError.isInstance(e)) {
console.error('repair failed:', e.cause, 'original:', e.originalError);
// fall back to an un-repaired retry or surface a friendly message
} else throw e;
} Prevention
- Wrap the body of your repair function in try/catch and return null on failure.
- Ensure the repair model has a valid API key and tool-calling support.
- Log e.cause to identify the underlying repair failure quickly.
When it happens
Trigger: Providing `experimental_repairToolCall` to generateText/streamText and the repair function (often itself an LLM call) throws — network failure, API error, or a bug inside the repair callback.
Common situations: Repair prompt calling a model with invalid/missing API key; repair function throwing on unexpected input; timeout inside the repair LLM call; passing an async repair that rejects.
Related errors
- Model tried to call unavailable tool '${toolName}'. No tools
- Invalid input for tool ${toolName}: ${getErrorMessage(cause)
- Model tried to call unavailable tool '${toolName}'. Availabl
- Google schema conversion does not support recursive JSON Sch
- Failed to download ${url}: ${cause}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/7417caf243a9cb04.
Report an issue: GitHub.