{"record":{"id":"3873734764717696","repo":"can1357/oh-my-pi","slug":"tool-call-rejected-by-user-target-name","errorCode":null,"errorMessage":"Tool call rejected by user (${target.name})","messagePattern":"Tool call rejected by user \\((.+?)\\)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"info","filePath":"packages/coding-agent/src/session/session-tools.ts","lineNumber":838,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\tif (raced.kind === \"aborted\" || signal?.aborted) {\n\t\t\t\t\t\tthrow new ToolAbortError(\"Permission request cancelled\");\n\t\t\t\t\t}\n\t\t\t\t\tconst outcome = raced.outcome;\n\t\t\t\t\tif (outcome.outcome === \"cancelled\") {\n\t\t\t\t\t\tthrow new ToolAbortError(\"Permission request cancelled\");\n\t\t\t\t\t}\n\t\t\t\t\tconst selectedOption = PERMISSION_OPTIONS_BY_ID.get(outcome.optionId);\n\t\t\t\t\tif (!selectedOption) {\n\t\t\t\t\t\tthrow new ToolError(`Tool permission response used unknown option ID: ${outcome.optionId}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (selectedOption.kind === \"allow_always\") {\n\t\t\t\t\t\tthis.#acpPermissionDecisions.set(permissionIntent.cacheKey, \"allow_always\");\n\t\t\t\t\t} else if (selectedOption.kind === \"reject_always\") {\n\t\t\t\t\t\tthis.#acpPermissionDecisions.set(permissionIntent.cacheKey, \"reject_always\");\n\t\t\t\t\t}\n\t\t\t\t\tif (selectedOption.kind === \"reject_once\" || selectedOption.kind === \"reject_always\") {\n\t\t\t\t\t\tthrow new ToolError(`Tool call rejected by user (${target.name})`);\n\t\t\t\t\t}\n\t\t\t\t\treturn await target.execute(toolCallId, args as never, signal, onUpdate, ctx);\n\t\t\t\t};\n\t\t\t},\n\t\t}) as T;\n\t}\n\n\t#isExplicitAutoApproveMode(): boolean {\n\t\treturn (\n\t\t\tthis.#autoApprove ||\n\t\t\t(this.#host.settings.isConfigured(\"tools.approvalMode\") &&\n\t\t\t\tthis.#host.settings.get(\"tools.approvalMode\") === \"yolo\")\n\t\t);\n\t}\n\n\t/** Applies an enabled tool set and reconciles its `xd://` partition. */\n\tapplyActiveToolsByName(toolNames: string[], forcePromptRefresh = false, signal?: AbortSignal): Promise<void> {\n\t\treturn this.runToolRegistryMutation(","sourceCodeStart":820,"sourceCodeEnd":856,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/session-tools.ts#L820-L856","documentation":"The permission outcome selected a 'reject_once' or 'reject_always' option, so SessionTools refuses to execute the tool and throws ToolError with the tool's name. This is the library's representation of an explicit user denial — the model's tool call is blocked and the rejection (for reject_always) is cached for future calls with the same permission cache key.","triggerScenarios":"The permission prompt response mapped to an option with kind 'reject_once' or 'reject_always' (session-tools.ts:836-838); or an earlier reject_always decision was cached under `#acpPermissionDecisions` and replayed via the 'Tool call rejected by user (preference)' path.","commonSituations":"User clicked Deny/Reject on a tool permission dialog; an automated policy handler configured to reject certain tools; a previously saved 'always reject' preference auto-rejecting later calls.","solutions":["This is intended behavior — the agent loop should relay the rejection to the model as a tool error, not treat it as a crash.","To stop seeing rejections, remove the reject-always preference or re-approve the tool in permission settings.","If building an automated responder, return an allow option for trusted tools instead of reject."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await runTool();\n} catch (err) {\n  if (err instanceof ToolError && err.message.startsWith('Tool call rejected by user')) {\n    // relay denial to the model as a normal tool result\n    return { blocked: true, reason: err.message };\n  }\n  throw err;\n}","preventionTips":["Treat rejections as expected control flow, not exceptions to log as failures.","Audit saved reject-always preferences when tools 'mysteriously' stop running.","Provide clear allow options in custom permission UIs to reduce accidental denials."],"tags":["permissions","user-interaction","tool-execution","denial"],"backgroundTag":"tool-permission-denied","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}