{"record":{"id":"7f03ffda025b481c","repo":"moeru-ai/airi","slug":"select-this-tool-before-running-it-again","errorCode":null,"errorMessage":"Select this tool before running it again.","messagePattern":"Select this tool before running it again\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/chat.ts","lineNumber":500,"sourceCode":"\n    try {\n      return await executeSend({\n        sessionId: payload.sessionId,\n        text,\n        replyToMessageId: sourceMessage?.replyToMessageId,\n        tools: payload.tools ?? sourceMessage?.tools?.filter(tool => !requiresToolSelection(tool.name)),\n      })\n    }\n    catch (error) {\n      appendSendError(payload.sessionId, error)\n      throw error\n    }\n  }\n\n  /** Runs one stored tool call again and replaces its stored result. */\n  async function rerunToolCall(payload: ChatToolCallRerunPayload): Promise<void> {\n    if (requiresToolSelection(payload.toolName) && !payload.tools?.some(tool => tool.name === payload.toolName))\n      throw new Error('Select this tool before running it again.')\n\n    if (!await chatSession.loadSession(payload.sessionId))\n      throw new Error('Failed to load the target chat session')\n\n    const nextMessages = await executeToolCallRerun({\n      messages: chatSession.getSessionMessages(payload.sessionId),\n      payload,\n      resolveTools: () => resolveLlmTools({\n        customTools: llmToolsStore.getToolsByNames(payload.toolName),\n      }),\n    })\n    chatSession.setSessionMessages(payload.sessionId, nextMessages)\n  }\n\n  /** Clears one session and stops runtime work that still belongs to it. */\n  function cleanup(sessionId: string) {\n    chatSession.cleanupMessages(sessionId)\n    chatContext.resetContexts()","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/packages/stage-ui/src/stores/chat.ts#L482-L518","documentation":"rerunToolCall re-executes a previously stored tool call. Some tools are gated by requiresToolSelection: the caller must pass a tools list containing the tool being rerun. If the payload's tools array does not include payload.toolName, the store refuses to run it — the user must explicitly select/enable the tool before rerunning.","triggerScenarios":"Calling rerunToolCall({ toolName, ... }) where requiresToolSelection(toolName) is true and payload.tools is undefined or does not contain an entry with name === toolName.","commonSituations":"A UI 'retry this tool call' button that reruns without sending the currently enabled tool list; a tool disabled in settings after its original run; programmatically rerunning a gated tool without reconstructing the tools payload.","solutions":["Include the tool in payload.tools when calling rerunToolCall (the UI should pass the currently enabled tool definitions).","Have the user enable/select the tool in the chat UI before retrying.","Check requiresToolSelection(toolName) beforehand and prompt for selection instead of calling.","Verify the tool name string matches the registered tool's name exactly."],"exampleFix":"// before\nawait rerunToolCall({ sessionId, toolName: 'web_search' })\n// after\nawait rerunToolCall({ sessionId, toolName: 'web_search', tools: enabledTools })","handlingStrategy":"validation","validationCode":"const canRerun = !requiresToolSelection(payload.toolName)\n  || payload.tools?.some(t => t.name === payload.toolName)\nif (!canRerun) enableToolFirst(payload.toolName)","typeGuard":null,"tryCatchPattern":"try {\n  await rerunToolCall(payload)\n} catch (e) {\n  if (e.message === 'Select this tool before running it again.')\n    ui.promptToolSelection(payload.toolName)\n  else throw e\n}","preventionTips":["Always pass the full currently-enabled tool list in the rerun payload.","Disable retry buttons for tools not in the active tool set.","Match tool names against registered tool definitions, not free-form strings."],"tags":["chat","tool-call","validation","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}