chatboxai/chatbox · error · Error
Tool "${batchPart.toolName}" is not available
Error message
Tool "${batchPart.toolName}" is not available What it means
Thrown during batched execution of paused tool calls. After the user approves a paused batch, buildToolsForPausedToolCall rebuilds the toolset and each batch part is dispatched by name; if tools[batchPart.toolName] is absent or lacks an execute function, the call cannot run and the batch is aborted. This guards against dispatching a tool the session no longer exposes.
Source
Thrown at src/renderer/stores/session/orchestration.ts:1287
// time spent waiting for user approval / manual continuation.
startTime: Date.now(),
duration: undefined,
})
),
generating: true,
cancel: (stoppedAt = Date.now()) => controller.abort(stoppedAt),
}
await modifyMessage(sessionId, message, false)
try {
const { tools } = await buildToolsForPausedToolCall(session, settings, message)
for (const batchPart of batch) {
if (controller.signal.aborted) break
const toolValue = (tools as Record<string, unknown>)[batchPart.toolName]
const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
if (typeof executableTool?.execute !== 'function') {
throw new Error(`Tool "${batchPart.toolName}" is not available`)
}
try {
// Bind approval to the exact call the user reviewed. Never infer authorization from
// batch membership: a sibling call must pass through its own approval gate.
const result = await executableTool.execute(
batchPart.args,
createPausedToolCallExecutionContext(batchPart, approvedToolCallId, controller.signal)
)
message = updateToolCallPart(message, batchPart.toolCallId, (toolPart) => ({
...toolPart,
state: 'result',
pauseReason: undefined,
result,
duration: toolPart.startTime ? Date.now() - toolPart.startTime : undefined,
}))
} catch (error) {
if (controller.signal.aborted) {View on GitHub (pinned to 81571269ad)
Solutions
- Re-validate each batchPart.toolName against the rebuilt tools map and mark only missing ones as errored instead of aborting the whole batch.
- Prompt the user to re-resume after settings changes rather than failing silently.
- Keep tool names stable across versions and deprecate rather than rename.
- Log the available tool keys alongside the missing name to speed diagnosis.
Example fix
// before
const toolValue = (tools as Record<string, unknown>)[batchPart.toolName]
const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
if (typeof executableTool?.execute !== 'function') {
throw new Error(`Tool "${batchPart.toolName}" is not available`)
}
// after
const toolValue = (tools as Record<string, unknown>)[batchPart.toolName]
const executableTool = toolValue && typeof toolValue === 'object' ? (toolValue as ExecutableTool) : undefined
if (typeof executableTool?.execute !== 'function') {
message = updateToolCallPart(message, batchPart.toolCallId, (p) => ({ ...p, state: 'error', result: { error: `Tool "${batchPart.toolName}" is no longer available (settings changed?)` } }))
continue
} Defensive patterns
Strategy: validation
Validate before calling
const { tools } = await buildToolsForPausedToolCall(session, settings, message)
const missing = batch.filter((p) => typeof (tools as Record<string, unknown>)[p.toolName]?.execute !== 'function')
if (missing.length) {
// mark only those parts as errored, continue the rest
} 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 runBatch()
} catch (err) {
if (err instanceof Error && /is not available$/.test(err.message)) {
markToolPartsErrored(message, batch)
} else throw err
} Prevention
- Re-validate tool names against the rebuilt toolset and error per-part, not the whole batch.
- Keep tool identifiers stable across versions.
- Warn the user when settings changed since the call was paused.
When it happens
Trigger: buildToolsForPausedToolCall returns a tools map that does not include batchPart.toolName or includes a non-executable entry. Causes: settings changed between pause and approval (tool disabled, agent mode toggled off, knowledge base detached), the model emitted a tool name not in the allowed set, or a version change renamed/removed a tool.
Common situations: User paused on a tool call then changed settings (disabled agent mode, removed knowledge base, switched provider) before approving; a model hallucinated a tool name; a plugin/tool was unregistered in an update while a paused call waited.
Related errors
- Tool "${part.toolName}" is not available
- Custom provider "${providerId}" conflicts with a builtin pro
- The Agent Mode reward was claimed, but the interrupted task
- Invalid settings entry
- Image model is disabled in settings: ${provider}/${modelId}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/e7dc2d5fcea3837a.
Report an issue: GitHub.