can1357/oh-my-pi · error · Error

Tool execution was blocked by a hook

Error message

Tool execution was blocked by a hook

What it means

A hook handler for the tool-call event returned a result with block: true, forbidding execution of this tool call. The hook's reason string is used as the error message; this generic text is the fallback when the hook supplies no reason.

Source

Thrown at packages/coding-agent/src/extensibility/hooks/tool-wrapper.ts:58

		context?: AgentToolContext,
	) {
		// Emit tool_call event - hooks can block execution or revise the input the tool runs with.
		// If hook errors/times out, block by default (fail-safe)
		let effectiveParams = params;
		if (this.hookRunner.hasHandlers("tool_call")) {
			try {
				const callResult = (await this.hookRunner.emitToolCall({
					type: "tool_call",
					toolName: this.tool.name,
					toolCallId,
					input: normalizeToolEventInput(
						this.tool.name,
						resolveToolEventInput(this.tool, params as Record<string, unknown>),
					),
				})) as ToolCallEventResult | undefined;

				if (callResult?.block) {
					const reason = callResult.reason || "Tool execution was blocked by a hook";
					throw new Error(reason);
				}
				// A non-blocking handler may replace the execution input. The returned object is the raw
				// input the tool runs with (handler-owned); it is not re-normalized. Skipped for `computer`
				// tool calls, whose real parameters are not represented by the event input.
				if (callResult?.input !== undefined && context?.toolCall?.providerMetadata?.type !== "computer") {
					effectiveParams = callResult.input as Static<TParameters>;
				}
			} catch (err) {
				// Hook error or block - throw to mark as error
				if (err instanceof Error) {
					throw err;
				}
				throw new Error(`Hook failed, blocking execution: ${String(err)}`);
			}
		}

		// Execute the actual tool, forwarding onUpdate for progress streaming

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the hook's reason (if provided) to see which hook blocked and why
  2. Adjust or remove the blocking hook's matching rules to permit this call
  3. Run without the guardrail extension if it is blocking legitimate work
  4. Have the agent choose an alternative approach the hooks allow

Example fix

// hook result
// before
return { block: true };
// after (permit or explain)
return { block: false };
// or: return { block: true, reason: 'protected path' };
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: run your hook logic against the planned params before calling the tool
const verdict = myGuardHook(toolName, params);
if (verdict.block) throw new Error(verdict.reason || 'Tool execution was blocked by a hook');

Try / catch

try { await tool.execute(params); } catch (err) {
  if (err instanceof Error && err.message === 'Tool execution was blocked by a hook') {
    // hook gave no reason; audit installed hooks
  } else if (err instanceof Error && /* known block reason */ false) {
    // handle reasoned blocks
  } else throw err;
}

Prevention

When it happens

Trigger: A registered on-tool-call hook inspects the tool name/input and returns { block: true } (optionally with reason) during wrapper.execute(); blocking policy hooks, guardrail extensions, or audit hooks.

Common situations: Organization guardrail hooks blocking dangerous commands or protected file edits; users installing policy extensions that deny certain tools; hooks misfiring on legitimate calls due to over-broad matching.

Related errors


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