{"record":{"id":"21d084e0fe22a295","repo":"can1357/oh-my-pi","slug":"tool-execution-was-blocked-by-a-hook","errorCode":null,"errorMessage":"Tool execution was blocked by a hook","messagePattern":"Tool execution was blocked by a hook","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/hooks/tool-wrapper.ts","lineNumber":58,"sourceCode":"\t\tcontext?: AgentToolContext,\n\t) {\n\t\t// Emit tool_call event - hooks can block execution or revise the input the tool runs with.\n\t\t// If hook errors/times out, block by default (fail-safe)\n\t\tlet effectiveParams = params;\n\t\tif (this.hookRunner.hasHandlers(\"tool_call\")) {\n\t\t\ttry {\n\t\t\t\tconst callResult = (await this.hookRunner.emitToolCall({\n\t\t\t\t\ttype: \"tool_call\",\n\t\t\t\t\ttoolName: this.tool.name,\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tinput: normalizeToolEventInput(\n\t\t\t\t\t\tthis.tool.name,\n\t\t\t\t\t\tresolveToolEventInput(this.tool, params as Record<string, unknown>),\n\t\t\t\t\t),\n\t\t\t\t})) as ToolCallEventResult | undefined;\n\n\t\t\t\tif (callResult?.block) {\n\t\t\t\t\tconst reason = callResult.reason || \"Tool execution was blocked by a hook\";\n\t\t\t\t\tthrow new Error(reason);\n\t\t\t\t}\n\t\t\t\t// A non-blocking handler may replace the execution input. The returned object is the raw\n\t\t\t\t// input the tool runs with (handler-owned); it is not re-normalized. Skipped for `computer`\n\t\t\t\t// tool calls, whose real parameters are not represented by the event input.\n\t\t\t\tif (callResult?.input !== undefined && context?.toolCall?.providerMetadata?.type !== \"computer\") {\n\t\t\t\t\teffectiveParams = callResult.input as Static<TParameters>;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Hook error or block - throw to mark as error\n\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Hook failed, blocking execution: ${String(err)}`);\n\t\t\t}\n\t\t}\n\n\t\t// Execute the actual tool, forwarding onUpdate for progress streaming","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/hooks/tool-wrapper.ts#L40-L76","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// hook result\n// before\nreturn { block: true };\n// after (permit or explain)\nreturn { block: false };\n// or: return { block: true, reason: 'protected path' };","handlingStrategy":"try-catch","validationCode":"// pre-flight: run your hook logic against the planned params before calling the tool\nconst verdict = myGuardHook(toolName, params);\nif (verdict.block) throw new Error(verdict.reason || 'Tool execution was blocked by a hook');","typeGuard":null,"tryCatchPattern":"try { await tool.execute(params); } catch (err) {\n  if (err instanceof Error && err.message === 'Tool execution was blocked by a hook') {\n    // hook gave no reason; audit installed hooks\n  } else if (err instanceof Error && /* known block reason */ false) {\n    // handle reasoned blocks\n  } else throw err;\n}","preventionTips":["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"],"tags":["hook","blocked","guardrail","tool-execution"],"backgroundTag":"tool-call-blocked-by-hook","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}