{"version":"2.1.317","anchor":"stoppermission-hook-callbacks-gain-onfailure","canonical_anchor":"stoppermission-hook-callbacks-gain-onfailure","heading":"SDK hook callbacks can block an action when they fail, using onFailure","tier":"use","area":"Hooks","scope":"individual","heads_up":true,"url":"https:\/\/changelogs.core-directive.com\/v\/2.1.317\/e\/stoppermission-hook-callbacks-gain-onfailure","release_url":"https:\/\/changelogs.core-directive.com\/v\/2.1.317","markdown":"### SDK hook callbacks can block an action when they fail, using onFailure\n\nSDK hook callbacks can set onFailure to block so a failed check stops the action, and the SDK refuses to start if Claude Code cannot honour it\n\n**What**\n\nHooks are actions you set up to run automatically at set points while Claude Code works. Programs built on the Claude Agent SDK (the toolkit for running Claude Code from your own code) can register hook callbacks: functions in their own program that Claude Code calls. A hook matcher, the rule that decides which events a callback handles, now accepts an `onFailure` setting. It says what happens when the callback itself fails:\n\n- `onFailure: \"continue\"` is the default: a failed callback is ignored and the action goes ahead.\n\n- `onFailure: \"block\"` makes a failed callback count as a block, so the action does not run.\n\n- Any other value logs a warning and is treated as `\"block\"`. The value is passed to each callback.\n\n- The setting is ignored on the `Stop`, `SubagentStop`, `TaskCompleted` and `TeammateIdle` events.\n\n- `callback` hooks are now checked for this the same way as `http` hooks. Before, only command and http hook types were handled, and other types never blocked.\n\n- `createHookCallback` takes the `onFailure` value and sends it on as `hookOnFailure`. In block mode, a failed callback, or an answer that names a different hook event ('The answer names another hook event'), now raises an error, and waiting callbacks can be rejected. Before, failures were logged and swallowed, and the action carried on.\n\nThe SDK and Claude Code also check that they agree on this before any work starts:\n\n- Claude Code's reply to the opening `initialize` request now includes `hook_on_failure_supported`, which is true when that version honours `onFailure`. Older versions ignored the setting, so a failing callback set to block still let the action run.\n\n- The SDK sends each matcher's `onFailure` in the `initialize` request. If any hook uses a value other than `\"continue\"`, your first prompt is held until `initialize` succeeds. The SDK stops with an error if Claude Code does not report `hook_on_failure_supported`, or if `hooks_applied` is false on a session that is already running. If `initialize` is never answered, a timeout cleans up the query and the prompt is not sent.\n\n- Over a remote connection, when a pending hook callback is set to block, an error reply coming from a different client is ignored, and Claude Code keeps waiting for the program that registered the hook. A matching log line records this.\n\n**Why**\n\nIf you use SDK hooks as safety checks, you can now make them fail closed: a crashed or broken check stops the action instead of silently letting it through. The SDK refuses to send your prompt to a Claude Code version that cannot honour the setting, rather than running without the protection you asked for.\n\n- Area: Hooks\n- Names: `onFailure`\n- Tier: Use it now\n- Useful: 5\/5\n- Signal: 2\/5\n- Scope: individual\n- Heads-up: yes"}