{"record":{"id":"2340d4d7b21b7fe8","repo":"can1357/oh-my-pi","slug":"tool-call-denied-by-user-this-tool-name","errorCode":null,"errorMessage":"Tool call denied by user: ${this.tool.name}","messagePattern":"Tool call denied by user: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/extensibility/extensions/wrapper.ts","lineNumber":340,"sourceCode":"\t\t\t}\n\n\t\t\tconst uiContext = this.runner.getUIContext();\n\t\t\tconst basePrompt = formatApprovalPrompt(this.tool, resolvedArgs, approvalCheck.reason);\n\t\t\tconst safetyPrompt =\n\t\t\t\tpendingSafetyChecks.length > 0\n\t\t\t\t\t? `${basePrompt}\\nProvider safety checks:\\n${safetyCheckLines(pendingSafetyChecks).join(\"\\n\")}`\n\t\t\t\t\t: basePrompt;\n\t\t\tlet choice: string | undefined;\n\t\t\ttry {\n\t\t\t\tchoice = await uiContext.select(safetyPrompt, [\"Approve\", \"Deny\"]);\n\t\t\t} catch (err) {\n\t\t\t\tawait emitApprovalResolved(false, err instanceof Error ? err.message : \"approval aborted\");\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tconst approved = choice === \"Approve\";\n\t\t\tawait emitApprovalResolved(approved, approved ? undefined : \"denied by user\");\n\t\t\tif (!approved) {\n\t\t\t\tthrow new Error(`Tool call denied by user: ${this.tool.name}`);\n\t\t\t}\n\t\t\tif (pendingSafetyChecks.length > 0) {\n\t\t\t\tif (!context) throw new Error(\"Provider safety approval context is unavailable\");\n\t\t\t\tcontext.providerSafetyApproved = true;\n\t\t\t}\n\t\t}\n\n\t\t// Execute the actual tool\n\t\tlet result: AgentToolResult<TDetails, TParameters>;\n\t\tlet executionError: Error | undefined;\n\n\t\ttry {\n\t\t\t// A denied file write or delete inside this tool can be brokered to an\n\t\t\t// extension handler, and that registry is PROCESS-WIDE — so the session is\n\t\t\t// named here, the one place where every tool's execution and the runner\n\t\t\t// that owns the handlers are both in scope (`sdk.ts` wraps the whole tool\n\t\t\t// registry with this class whenever a runner exists). Inert with no\n\t\t\t// fallback registered: no scope is entered.","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/extensions/wrapper.ts#L322-L358","documentation":"The user was shown the approval prompt for this tool call and explicitly chose not to approve it. The wrapper emits an approval-resolved event with reason 'denied by user' and throws so the tool call is recorded as an error rather than executed.","triggerScenarios":"A user presses 'Deny' (or aborts via Esc producing a rejection that resolves to non-Approve) on the tool approval dialog during execution in an interactive UI.","commonSituations":"Agent attempts a destructive or unexpected command and the user declines; automated flows where a human in the loop denies an action; scripts driving the TUI that answer 'Deny'.","solutions":["If denial was accidental, re-issue the tool call and approve it","Pre-approve the tool via tools.approval.<toolName>: allow if prompts are too frequent","Adjust approvalMode to reduce prompting in trusted environments","Catch/handle the error upstream and instruct the agent to try a different approach"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isUserDenial(e: unknown): boolean { return e instanceof Error && e.message.startsWith('Tool call denied by user:'); }","tryCatchPattern":"try { await tool.execute(params); } catch (err) {\n  if (isUserDenial(err)) {\n    return { status: 'denied', tool: err.message.split(': ')[1] };\n  }\n  throw err;\n}","preventionTips":["Treat denial as an expected control-flow outcome, not a crash","Instruct agents to propose alternative approaches after a denial","Use allow rules to cut prompt fatigue so users deny less by accident","Emit approval-resolved telemetry to track denial rates"],"tags":["user-denied","approval-gate","tool-execution"],"backgroundTag":"tool-call-denied-by-user","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}