{"record":{"id":"7127ec38528ff43b","repo":"chatboxai/chatbox","slug":"tool-part-toolname-is-not-available","errorCode":null,"errorMessage":"Tool \"${part.toolName}\" is not available","messagePattern":"Tool \"(.+?)\" is not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/stores/session/orchestration.ts","lineNumber":1451,"sourceCode":"    if (!settings) return\n\n    let retryMessage = updateToolCallPart(retrySourceMessage, toolCallId, (toolPart) => ({\n      ...toolPart,\n      state: 'call',\n      result: undefined,\n      resultStorageKey: undefined,\n      resultProviderMetadata: undefined,\n      startTime: Date.now(),\n      duration: undefined,\n    }))\n    await modifyMessage(sessionId, retryMessage, false)\n\n    try {\n      const { tools } = await buildToolsForPausedToolCall(session, settings, retryMessage)\n      const toolValue = (tools as Record<string, unknown>)[part.toolName]\n      const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined\n      if (typeof executableTool?.execute !== 'function') {\n        throw new Error(`Tool \"${part.toolName}\" is not available`)\n      }\n\n      const result = await executableTool.execute(part.args, {\n        toolCallId,\n        approved: true,\n        approvalDetails: part.pauseReason?.type === 'app_action_approval' ? part.pauseReason.details : undefined,\n      })\n      retryMessage = updateToolCallPart(retryMessage, toolCallId, (toolPart) => ({\n        ...toolPart,\n        state: 'result',\n        pauseReason: undefined,\n        result,\n        duration: toolPart.startTime ? Date.now() - toolPart.startTime : undefined,\n      }))\n      await modifyMessage(sessionId, retryMessage, true)\n\n      await orchestrateGeneration(\n        sessionId,","sourceCodeStart":1433,"sourceCodeEnd":1469,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/stores/session/orchestration.ts#L1433-L1469","documentation":"Thrown during single-call retry of a paused tool call (the retryToolCall path). buildToolsForPausedToolCall rebuilds the toolset; if part.toolName is not present or its entry has no execute function the retry cannot proceed. Same root cause as the batch path but for a one-shot retry.","triggerScenarios":"User retries a paused tool call after the tool became unavailable: settings changed (agent mode off, knowledge base removed, provider switched), tool renamed/removed in an update, or the model originally emitted a name not in the rebuilt set.","commonSituations":"Settings edited between pause and retry, plugin/tool unregistered by an update while a paused call waited, agent mode toggled off so the tool map no longer contains the action tool.","solutions":["Check tool availability before showing the retry button (rebuild tools lazily and test the name).","On this error, mark the part as errored with a clear 'tool no longer available' message instead of a generic throw.","Keep tool identifiers stable across releases.","If agent mode was turned off, prompt the user to re-enable it before retrying action tools."],"exampleFix":"// before\nconst toolValue = (tools as Record<string, unknown>)[part.toolName]\nconst executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined\nif (typeof executableTool?.execute !== 'function') {\n  throw new Error(`Tool \"${part.toolName}\" is not available`)\n}\n// after\nconst toolValue = (tools as Record<string, unknown>)[part.toolName]\nconst executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined\nif (typeof executableTool?.execute !== 'function') {\n  retryMessage = updateToolCallPart(retryMessage, toolCallId, (p) => ({ ...p, state: 'error', result: { error: `Tool \"${part.toolName}\" is no longer available` } }))\n  await modifyMessage(sessionId, retryMessage, true)\n  return\n}","handlingStrategy":"validation","validationCode":"const { tools } = await buildToolsForPausedToolCall(session, settings, retryMessage)\nif (!isExecutableTool((tools as Record<string, unknown>)[part.toolName])) {\n  // mark this part errored with a clear reason, do not throw\n}","typeGuard":"function isExecutableTool(v: unknown): v is { execute: (...args: unknown[]) => Promise<unknown> } {\n  return typeof v === 'object' && v !== null && typeof (v as { execute?: unknown }).execute === 'function'\n}","tryCatchPattern":"try {\n  await retryToolCall()\n} catch (err) {\n  if (err instanceof Error && /is not available$/.test(err.message)) {\n    markPartErrored(retryMessage, toolCallId, err.message)\n  } else throw err\n}","preventionTips":["Check tool availability before showing the retry button.","Prompt re-enabling agent mode if action tools went missing.","Keep tool identifiers stable across releases."],"tags":["tools","agent-mode","paused-call","retry","orchestration"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}