chatboxai/chatbox · error · Error

Tool "${part.toolName}" is not available

Error message

Tool "${part.toolName}" is not available

What it means

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.

Source

Thrown at src/renderer/stores/session/orchestration.ts:1451

    if (!settings) return

    let retryMessage = updateToolCallPart(retrySourceMessage, toolCallId, (toolPart) => ({
      ...toolPart,
      state: 'call',
      result: undefined,
      resultStorageKey: undefined,
      resultProviderMetadata: undefined,
      startTime: Date.now(),
      duration: undefined,
    }))
    await modifyMessage(sessionId, retryMessage, false)

    try {
      const { tools } = await buildToolsForPausedToolCall(session, settings, retryMessage)
      const toolValue = (tools as Record<string, unknown>)[part.toolName]
      const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
      if (typeof executableTool?.execute !== 'function') {
        throw new Error(`Tool "${part.toolName}" is not available`)
      }

      const result = await executableTool.execute(part.args, {
        toolCallId,
        approved: true,
        approvalDetails: part.pauseReason?.type === 'app_action_approval' ? part.pauseReason.details : undefined,
      })
      retryMessage = updateToolCallPart(retryMessage, toolCallId, (toolPart) => ({
        ...toolPart,
        state: 'result',
        pauseReason: undefined,
        result,
        duration: toolPart.startTime ? Date.now() - toolPart.startTime : undefined,
      }))
      await modifyMessage(sessionId, retryMessage, true)

      await orchestrateGeneration(
        sessionId,

View on GitHub (pinned to 81571269ad)

Solutions

  1. Check tool availability before showing the retry button (rebuild tools lazily and test the name).
  2. On this error, mark the part as errored with a clear 'tool no longer available' message instead of a generic throw.
  3. Keep tool identifiers stable across releases.
  4. If agent mode was turned off, prompt the user to re-enable it before retrying action tools.

Example fix

// before
const toolValue = (tools as Record<string, unknown>)[part.toolName]
const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
if (typeof executableTool?.execute !== 'function') {
  throw new Error(`Tool "${part.toolName}" is not available`)
}
// after
const toolValue = (tools as Record<string, unknown>)[part.toolName]
const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
if (typeof executableTool?.execute !== 'function') {
  retryMessage = updateToolCallPart(retryMessage, toolCallId, (p) => ({ ...p, state: 'error', result: { error: `Tool "${part.toolName}" is no longer available` } }))
  await modifyMessage(sessionId, retryMessage, true)
  return
}
Defensive patterns

Strategy: validation

Validate before calling

const { tools } = await buildToolsForPausedToolCall(session, settings, retryMessage)
if (!isExecutableTool((tools as Record<string, unknown>)[part.toolName])) {
  // mark this part errored with a clear reason, do not throw
}

Type guard

function isExecutableTool(v: unknown): v is { execute: (...args: unknown[]) => Promise<unknown> } {
  return typeof v === 'object' && v !== null && typeof (v as { execute?: unknown }).execute === 'function'
}

Try / catch

try {
  await retryToolCall()
} catch (err) {
  if (err instanceof Error && /is not available$/.test(err.message)) {
    markPartErrored(retryMessage, toolCallId, err.message)
  } else throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/7127ec38528ff43b. Report an issue: GitHub.