{"record":{"id":"3f68beb29545691c","repo":"moeru-ai/airi","slug":"assistant-message-does-not-contain-tool-call-pa","errorCode":null,"errorMessage":"Assistant message does not contain tool call \"${payload.toolCallId}\" for \"${payload.toolName}\".","messagePattern":"Assistant message does not contain tool call \"(.+?)\" for \"(.+?)\"\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/tool-call-rerun.ts","lineNumber":88,"sourceCode":"\n/**\n * Re-executes a stored tool call with supplied arguments and returns updated chat history.\n *\n * The resolver is injected so callers can choose the runtime-specific tool list\n * without coupling this helper to app-local stores, Electron IPC, or browser state.\n */\nexport async function executeToolCallRerun<TToolset extends string = string>(\n  options: ExecuteToolCallRerunOptions<TToolset>,\n): Promise<ChatHistoryItem[]> {\n  const { messages, payload } = options\n  const targetIndex = findTargetMessageIndex(messages, payload)\n  const targetMessage = messages[targetIndex]\n\n  if (targetMessage?.role !== 'assistant')\n    throw new Error('Tool call rerun target must be an assistant message.')\n\n  if (!hasMatchingToolCall(targetMessage, payload))\n    throw new Error(`Assistant message does not contain tool call \"${payload.toolCallId}\" for \"${payload.toolName}\".`)\n\n  const replaceTargetMessage = (result: ToolCallResultInput) => messages.map((item, itemIndex) => {\n    if (itemIndex !== targetIndex)\n      return item\n\n    return replaceToolCallResult(targetMessage, result)\n  })\n\n  const tools = await options.resolveTools()\n  const tool = tools.find(candidate => toolNameFrom(candidate) === payload.toolName)\n  if (tool == null) {\n    return replaceTargetMessage({\n      id: payload.toolCallId,\n      isError: true,\n      result: `Tool \"${payload.toolName}\" is not available for rerun in this runtime.`,\n    })\n  }\n","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/stores/tool-call-rerun.ts#L70-L106","documentation":"The target assistant message exists but contains no tool call matching payload.toolCallId and payload.toolName. hasMatchingToolCall compares ids stored on the assistant message; replaceToolCallResult needs an exact match to splice the new result in, so a mismatch aborts the rerun before any tool executes.","triggerScenarios":"The assistant message was regenerated so its tool call got a new id while the payload kept the old one; streaming stopped mid-response leaving the message without tool-call parts; history sync or merge dropped/rekeyed tool call ids.","commonSituations":"Clicking a rerun affordance rendered from a pre-regeneration snapshot; providers emitting different toolCallId formats across versions; history dedupe rewriting ids.","solutions":["Refresh history and trigger the rerun from the current assistant message's tool-call block.","Ensure the UI passes the toolCallId exactly as stored (no trimming or re-casing).","If messages are transformed, preserve toolCallId values or invalidate rerun actions.","Log the tool call ids present on the target message versus the payload to confirm the mismatch."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const target = messages[findTargetMessageIndex(messages, payload)]\nconst hasCall = !!target && target.role === 'assistant'\n  && listToolCallIds(target).includes(payload.toolCallId)\nif (!hasCall) {\n  // hide/disable the rerun action\n}","typeGuard":"function assistantHasToolCall(m: ChatHistoryItem | undefined, toolCallId: string): m is ChatHistoryItem & { role: 'assistant' } {\n  return !!m && m.role === 'assistant' && listToolCallIds(m).includes(toolCallId)\n}","tryCatchPattern":"catch (e) {\n  const msg = errorMessageFrom(e) ?? ''\n  if (msg.includes('does not contain tool call'))\n    await reloadHistory()\n  else\n    throw e\n}","preventionTips":["Bind rerun buttons to the toolCallId rendered from that exact message version.","Invalidate pending rerun actions whenever the messages array is replaced.","Diff toolCallIds when migrating or compacting history."],"tags":["tool-call","id-mismatch","chat-history","rerun"],"backgroundTag":"tool-call-id-mismatch","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}