can1357/oh-my-pi · error · Error

Tool "${this.tool.name}" requires approval but no interactiv

Error message

Tool "${this.tool.name}" requires approval but no interactive UI available.
Options:
  1. Set tools.approvalMode: yolo in /settings
  2. Add tools.approval.${this.tool.name}: allow to config
  3. Use an interactive UI to approve the tool call

What it means

The tool requires tier approval, but no interactive UI is available to prompt the user, so execution is refused. Unlike provider safety checks, ordinary approval CAN be satisfied via configuration (yolo mode or an explicit allow rule), which is what the error message suggests.

Source

Thrown at packages/coding-agent/src/extensibility/extensions/wrapper.ts:315

					sessionId,
					toolName: this.tool.name,
					toolCallId,
					approved,
					...(reason ? { reason } : {}),
				});
			};

			// Provider safety checks fail closed without an interactive prompt. Unlike
			// ordinary tier approval, no setting or yolo mode may bypass this gate.
			if (!this.runner.hasUI()) {
				const reason = "no interactive UI available";
				await emitApprovalResolved(false, reason);
				if (pendingSafetyChecks.length > 0) {
					throw new Error(
						`Tool "${this.tool.name}" has pending provider safety checks but no interactive UI is available.`,
					);
				}
				throw new Error(
					`Tool "${this.tool.name}" requires approval but no interactive UI available.\n` +
						`Options:\n` +
						`  1. Set tools.approvalMode: yolo in /settings\n` +
						`  2. Add tools.approval.${this.tool.name}: allow to config\n` +
						`  3. Use an interactive UI to approve the tool call`,
				);
			}

			const uiContext = this.runner.getUIContext();
			const basePrompt = formatApprovalPrompt(this.tool, resolvedArgs, approvalCheck.reason);
			const safetyPrompt =
				pendingSafetyChecks.length > 0
					? `${basePrompt}\nProvider safety checks:\n${safetyCheckLines(pendingSafetyChecks).join("\n")}`
					: basePrompt;
			let choice: string | undefined;
			try {
				choice = await uiContext.select(safetyPrompt, ["Approve", "Deny"]);
			} catch (err) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Set tools.approvalMode: yolo in settings to auto-approve all tools in trusted environments
  2. Add an allow rule for this specific tool: tools.approval.<toolName>: allow in config
  3. Run via an interactive UI so the approval prompt can be answered
  4. Programmatically supply an approval resolver in the SDK embedding

Example fix

// config (JSON)
// before
"tools": {}
// after
"tools": { "approval": { "bash": "allow" } }
Defensive patterns

Strategy: validation

Validate before calling

const needsApproval = resolveApprovalPolicy(toolName) !== 'allow';
if (needsApproval && !runner.hasUI()) throw new Error(`tool ${toolName} will fail headless: pre-approve via tools.approval config`);

Try / catch

try { await tool.execute(params); } catch (err) {
  if (err instanceof Error && err.message.includes('requires approval but no interactive UI')) {
    // pre-approve via config or switch to interactive mode and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Executing a tool whose resolved approval policy is not 'allow' while this.runner.hasUI() is false and no provider safety checks are pending; headless/SDK/RPC execution of tools that normally prompt.

Common situations: Headless scripts calling approval-gated tools (bash, edit) without UI; CI pipelines; misconfigured environments where approvalMode or per-tool allow rules were not set.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/946455510da797b0. Report an issue: GitHub.