{"record":{"id":"5666c152a42d9450","repo":"can1357/oh-my-pi","slug":"pending-action-store-unavailable-for-custom-tools","errorCode":null,"errorMessage":"Pending action store unavailable for custom tools in this runtime.","messagePattern":"Pending action store unavailable for custom tools in this runtime\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/custom-tools/loader.ts","lineNumber":156,"sourceCode":"\t\t\tsourceToolName: string;\n\t\t\tapply(reason: string): Promise<AgentToolResult<unknown>>;\n\t\t\treject?(reason: string): Promise<AgentToolResult<unknown> | undefined>;\n\t\t}) => void,\n\t) {\n\t\tthis.#sharedApi = {\n\t\t\tcwd,\n\t\t\texec: (command: string, args: string[], options?: ExecOptions) =>\n\t\t\t\texecCommand(command, args, options?.cwd ?? cwd, options),\n\t\t\tui: createNoOpUIContext(),\n\t\t\thasUI: false,\n\t\t\tlogger,\n\t\t\ttypebox,\n\t\t\tarktype: type,\n\t\t\tzod,\n\t\t\tpi,\n\t\t\tpushPendingAction: action => {\n\t\t\t\tif (!pushPendingAction) {\n\t\t\t\t\tthrow new Error(\"Pending action store unavailable for custom tools in this runtime.\");\n\t\t\t\t}\n\t\t\t\tpushPendingAction({\n\t\t\t\t\tlabel: action.label,\n\t\t\t\t\tsourceToolName: action.sourceToolName ?? \"custom_tool\",\n\t\t\t\t\tapply: action.apply,\n\t\t\t\t\treject: action.reject,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t\tthis.#seenNames = new Set<string>(builtInToolNames);\n\t}\n\n\tasync load(pathsWithSources: ToolPathWithSource[]): Promise<void> {\n\t\tfor (const { path: toolPath, source } of pathsWithSources) {\n\t\t\tconst { tools: loadedTools, errors } = await loadTool(toolPath, this.#sharedApi.cwd, this.#sharedApi, source);\n\t\t\tthis.errors.push(...errors);\n\n\t\t\tfor (const loadedTool of loadedTools) {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/custom-tools/loader.ts#L138-L174","documentation":"CustomToolLoader's shared API exposes pi.pushPendingAction to custom tools, but the closure only forwards to a real pending-action store when one was injected via the loader constructor's optional pushPendingAction parameter. In runtimes that do not supply one (e.g. headless/SDK embedding without UI action support), the API stub throws this error when a custom tool attempts to register a pending (confirmable) action.","triggerScenarios":"A custom tool calls pi.pushPendingAction({label, apply, ...}) while running in a runtime where CustomToolLoader was constructed without the pushPendingAction callback — e.g. RPC/SDK/non-interactive contexts where pending UI actions aren't wired.","commonSituations":"Writing a custom tool that uses pending actions and testing it in an SDK/embedded runtime; running the agent headless where the interactive UI action store doesn't exist; a tool written for the TUI being reused in a background job.","solutions":["Guard the tool: check whether pending actions are supported in the runtime before registering, or wrap the call in try/catch and degrade gracefully (auto-apply instead of asking).","Run the tool in the interactive TUI runtime where the pending action store is provided to CustomToolLoader.","If you embed the SDK and need pending actions, pass a pushPendingAction implementation when constructing CustomToolLoader."],"exampleFix":"// before (inside custom tool)\npi.pushPendingAction({ label: 'Apply migration?', apply });\n// after\ntry {\n  pi.pushPendingAction({ label: 'Apply migration?', apply });\n} catch {\n  await apply('pending actions unsupported in this runtime'); // auto-apply fallback\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  pi.pushPendingAction({ label, apply });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Pending action store unavailable')) {\n    await apply('pending actions unsupported; auto-applying');\n  } else throw err;\n}","preventionTips":["Only use pending actions in interactive (TUI) runtimes","Provide an auto-apply fallback path in custom tools that request confirmation","Document runtime requirements in custom tool READMEs","If embedding the SDK, pass a pushPendingAction implementation to CustomToolLoader"],"tags":["custom-tools","extensions","unsupported-operation","runtime"],"backgroundTag":"api-unavailable-in-runtime","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}