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 streamingView on GitHub (pinned to 9690622007)
Solutions
- Read the hook's reason (if provided) to see which hook blocked and why
- Adjust or remove the blocking hook's matching rules to permit this call
- Run without the guardrail extension if it is blocking legitimate work
- 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
- Always provide a reason when a hook blocks, for diagnosability
- Keep hook matching rules narrow and tested
- Audit installed extensions/hooks before headless automation runs
- Maintain an allowlist of tools your automation needs and mirror it in hooks
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
- ${reason}
- Hook failed, blocking execution: ${String(err)}
- Extension failed, blocking execution: ${String(err)}
- Tool call denied by user: ${this.tool.name}
- Permission request cancelled
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/21d084e0fe22a295.
Report an issue: GitHub.