CC for Biz
2026/10/11Claude Code
セキュリティAI活用

Claude Code onFailureとは|フック失敗で停止

Claude Code onFailureとは|フック失敗で停止

「Claude Codeのフックで危ないコマンドを止めているつもりだったのに、スクリプトが落ちていたら素通りしていた」——フックを安全装置として使い始めた人ほど、この不安にいつか行き当たります。

結論から言うと、Claude Code 2.1.295(2026年10月8日公開)で加わった "onFailure": "block" をフックに1行足せば、フックが起動できない・時間切れになる・想定外の終了コードで落ちるといった「フック自体の故障」のときに、その操作を止められます。既定値は "continue" で、何も書かなければ今までどおり素通りします。ただし私の実測では、付けても止まらない書き方と、付けなくても偶然止まる書き方がありました。

株式会社Fyveは、Claude Codeのフックで契約書・公開記事・ポストの検査を自動で回しています。この記事では公式ドキュメントの仕様を正として押さえたうえで、自分の環境のフック7本を棚卸しした結果と、7通りの設定で実際に止まるかを試した結果から、「どのフックを止める側に倒すか」の決め方までをまとめます。

onFailureとは——フックが「壊れた」ときの扱いを選ぶ設定

onFailure は、フックが失敗したときに元の操作をどうするかを決める項目です。値は2つだけです。

  • "continue"(既定):フックが失敗しても、操作はそのまま実行される
  • "block":フックが失敗したら、操作を止める

公式ドキュメントのフックのページは、この設定が必要な理由をこう書いています。「多くのイベントでは、フックが失敗したり時間切れになったりしても Claude Code は操作を実行する。そのため、パスを間違えたポリシーのフックや、落ちるスクリプトは、すべてを素通りさせる」。

つまり今までのフックは、検査で「ダメ」と判定されたときは止まるが、検査そのものが動かなかったときは通る作りでした。安全装置としては、いちばん困る壊れ方で黙って開く、ということです。onFailure: "block" は、この「装置が壊れたとき」の向きを利用者が選べるようにしたものです。

使えるバージョンと対象のフック

  • バージョン:Claude Code v2.1.295 以降(公式 CHANGELOG と公式ドキュメントに記載。2026年10月9日付のクラスメソッドの解説記事も、2.1.295 の公開日を2026年10月8日としています)
  • 対象のフック:command(シェルのコマンドを実行するフック)と http(URLへ送るフック)の2種類だけ。公式ドキュメントで onFailure が載っているのはこの2つの項目表のみで、prompt・agent・MCP ツールのフックには記載がありません

私の手元は 2.1.296(10月12日時点)です。まず claude --version で 2.1.295 以上かを確かめてください。古い版では書いても無視されます。

設定のしかた——フックに1行足すだけ

公式ドキュメントの例をもとにすると、Bash の実行前に検査するフックを止める側に倒す設定は次のとおりです。.claude/settings.json の該当フックに "onFailure": "block" を足します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node",
            "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js"],
            "onFailure": "block"
          }
        ]
      }
    ]
  }
}

スクリプトが見つからないとき、画面にはこう出ます(公式ドキュメントの表示例)。

PreToolUse:Bash hook error: [...]: failed; blocking because onFailure is "block"

時間切れのときは failed の代わりに timed out と表示されます。

この記事を読んでいるあなたへ無料プレゼントClaudeのこの5つの設定、今すぐ見直した方がいい共有・学習・入力・権限・委任。事故が起きるのはこの5つだけ(全28ページ)
見落としやすい共有リストは3つある(3つ目は画面の下)学習をオフにしても残る、公式の例外条項権限モード6つの違いと、Shift+Tabでの切り替え方
中身のプレビューを見る ↓登録すると、過去の特典もまとめて受け取れます(PDF 17点・合計440ページ + すぐ使えるzip素材 3点)

何が「失敗」に数えられるか——公式の5条件

ここを取り違えると設定の意味がなくなります。公式ドキュメントが挙げている「失敗」は次の5つです。

失敗の種類

中身

起動できない

スクリプトや実行ファイルが存在しない等で、command フックが始まらない

0と2以外の終了コード

許可の JSON(permissionDecision: "allow" 等)を出していても失敗扱い。JSON で判定を返すなら終了コードは0にする

HTTP のエラー

http フックの接続失敗、または 2xx 以外の応答

時間切れ

フックに設定した timeout に達した

出力が壊れている

JSON が読めない、または形式の検査に通らない。command フックが普通の文字を出すだけなら失敗ではない

大事なのは、終了コード2は失敗に入らないことです。2は「意図して止める」ための正式な合図で、PreToolUse なら道具の実行を止め、UserPromptSubmit なら入力を退けます。onFailure の外側にある、もともとの仕組みです。

そして "block" のときに失敗が起きると、そのイベントで終了コード2を返したのと同じ動きになります。例外は PermissionRequest(許可の確認を出す場面)で、ここでは止めるのではなく「拒否」になります。

効かないところ——Stop系の4つと、裏で動くフック

onFailure を書いても効かない場所が2つあります。

  • Stop・SubagentStop・TaskCompleted・TeammateIdle:これらのイベントで終了コード2を返すと、Claude は「作業を続けろ」と差し戻されます。しかし動かないフックを Claude が直せるわけではないので、公式は対象外にしています
  • async または asyncRewake を付けた command フック:裏で動くフックは操作を待たせないので、止めようがありません

「作業の終わりに必ず検査を走らせる」目的で Stop フックを置いている場合、そのフックが壊れたら onFailure では拾えません。ここは別の手当てが要ります(後半で触れます)。

7通りの設定で、本当に止まるかを試した

仕様を読んだだけでは、手元の書き方で効くかは分かりません。そこで2026年10月12日に、PreToolUse(Bash の実行前)にフックを1本だけ置いた検証用のフォルダを7つ作り、Claude Code に「Bash で1行ファイルに書き込む」よう頼んで、ファイルができたかどうかで判定しました。版は 2.1.296、ヘッドレス実行(claude -p)です。

7通りのフック設定でBashが止まったか素通りしたかの実測表。python3で存在しないスクリプトは終了コード2で偶然止まり、exit 0で抜けるラッパー経由はblockでも素通りした

結果から分かったことは3つあります。

1. onFailureなしでも「偶然止まる」ことがある

1番は onFailure を書いていないのに止まりました。理由は終了コードです。手元で確かめると、存在しないファイルを渡したとき python3 は2、sh は127、node は1を返しました。Python は「ファイルが無い」を2で返すので、Claude Code から見ると「意図した拒否」と区別がつきません。

同じ「スクリプトが無い」でも、sh で呼んでいた4番は素通りしています。つまり今まで「フックが壊れたら止まっていた」経験がある人も、それは仕様ではなく、たまたま Python で呼んでいたからかもしれません。

私たちはこれで一度痛い目を見ています。2026年7月31日、無人ジョブを回している別の Mac で、フック本体のパスを特定の環境に固定していたせいでスクリプトが見つからず、Bash が丸一日すべて止まりました。当時は「終了コードが0以外だったから拒否扱いになった」と記録していましたが、今回の実測と照らすと、Python がファイル無しで返す2が「拒否」として読まれた、というのが正確な説明だと考えています。

2. 「無ければ exit 0」のラッパーは、blockを無効にする

いちばん大事なのが3番です。"block" を付けたのに素通りしました。

この書き方は、上の事故のあとで私たち自身が全フックに入れていたものです。

sh -c 'H="$CLAUDE_PROJECT_DIR/.../check.py"; [ -f "$H" ] || { cat >/dev/null; exit 0; }; exec python3 "$H"'

「スクリプトが無ければ、入力を読み捨てて正常終了する」というガードです。丸一日止まる事故を二度と起こさないために、通す側へ倒しました。ところがこのガードがあると、Claude Code から見たフックは「成功した(終了コード0)」ので、失敗として数えられません。onFailure は何もしないまま、スクリプトの無いフックが黙って通ります。

block に切り替えるなら、ラッパー側の「無ければ exit 0」も同時に外す必要があります。片方だけ直すと、設定ファイルを読んだ人には止まるように見えて、実際は通る、といういちばん見つけにくい状態になります。

3. 中身の例外は、blockで初めて止まる

6番と7番は、スクリプトは存在するが中で例外が起きて落ちる(終了コード1)場合です。onFailure なしでは素通り、"block" ありでは止まりました。表示も公式どおり failed; blocking because onFailure is "block" でした。

検査のスクリプトは、読み込むファイルの形式が想定と違う、依存するライブラリが入っていない、といった理由で普通に落ちます。「検査に通らなかった」と「検査が動かなかった」を区別して止めたいなら、この7番の状態をなくすのが onFailure の本当の使いどころです。

なお、クラスメソッドの検証記事(2026年10月9日)によると、UserPromptSubmit のフックを "block" で止めても claude -p 自体は終了コード0で終わるそうです。無人ジョブで「止まったかどうか」を判定するなら、プロセスの終了コードではなく、作業の結果(ファイルができたか等)で見る必要があります。私の7通りの検証も、その方法で判定しています。

自分のフック7本を棚卸ししたら、全部が素通りの設定だった

次に、本番で使っている .claude/settings.json のフックを数えました。PreToolUse が3本、PostToolUse が2本、Stop が2本の計7本です。

  • onFailure を書いていたもの:0本(2.1.295 より前に作ったので当然です)
  • 7本すべてが、上の「無ければ exit 0」ラッパー経由。スクリプトが消えたら全部通る
  • スクリプトはあるが中で落ちた場合も、Python の例外は終了コード1なので全部通る

面白いのは、このうち契約書の検査フックは、作った2026年7月30日の時点で方針をはっきり書いていたことです。スクリプト冒頭のコメントにはこうあります。「文書に欠陥がある → 止める(fail-closed)。検証器が無い等の仕組みの故障 → 通す(fail-open)。ワークフロー全体を壊さないため」。

当時はフックの故障で止める手段が実質なく、止めたいなら Python の終了コード2のような偶然に頼るしかありませんでした。だから「故障なら通す」が唯一の現実的な選択でした。2.1.295 で初めて、故障のときも止める、を設定として選べるようになったわけです。

フックが黙って動いていない問題そのもの(照合に失敗したフックが飛ばされていた件や、時間切れで出力が捨てられる件)は、10月3日の記事で詳しく書いています。今回の onFailure は、その記事の「終了コード1では止まらない」という落とし穴への、公式の答えにあたります。

Claude Codeのフックが効かない|黙って飛ばされる2条件
Claude CodeClaude Codeのフックが効かない|黙って飛ばされる2条件

どのフックを "block" にするか——3つの問いで決める

では、全部を "block" にすればよいかというと、そうではありません。フックが壊れるたびに作業が止まるなら、それはそれで7月31日の再現です。私は次の3つの問いを順に当てて決めました。

onFailureをblockにするか決める3つの問い。イベントで効くか、素通りしたとき何が外に出るか、止めたとき何まで止まるか。手元の7本は対象外2本、continue2本、block候補3本

問い1:そのイベントで onFailure が効くか

Stop フックの2本(作業の終わりに管理情報の更新漏れを点検するもの、会話に貼ったスクリーンショットを保存するもの)は、そもそも対象外です。ここは onFailure を書いても意味がありません。

問い2:素通りしたとき、何が外に出るか

判断の軸はこれです。素通りした結果が取り消せるかどうか。

  • PostToolUse の2本(ファイル編集のあとに「管理情報も更新して」と促すもの、契約書を編集した直後に検査結果を知らせるもの)は、どちらも注意を促すだけです。PostToolUse は道具が実行された後に走るので、止める対象もありません。ここは "continue" のままにしました
  • PreToolUse の3本(契約書のPDFを出す前の検査、公開するポストの文体の検査、公開する記事の検査)は、素通りすると客に渡る書類や、実名で公開される文章がそのまま外に出ます。出てから取り消すことはできません

問い3:止めたとき、何まで止まるか

ここが見落としやすいところです。私の PreToolUse の3本は、どれも matcher(フックを発動させる道具の指定)が Bash 全体です。中身は「契約書のPDFを作るコマンドのときだけ検査する」作りですが、フック本体が壊れれば、契約書と関係のない Bash まで全部止まります。

それでも私は、この3本は "block" 側に倒すのが正しいと判断しました。理由は、止まったときは画面にフック名つきのエラーが出て原因がすぐ分かるのに対し、素通りしたときは何も出ず、気づくのは客や読者に届いた後だからです。丸一日止まった7月31日の件も、困りはしましたが、誤った書類が外に出たわけではありません。

逆に、止まる範囲を許容できないなら、先に matcher を狭めるのが筋です。たとえば記事の検査なら、検査対象のファイルを書くときだけ発動するように指定を分ければ、壊れたときの影響もそこに閉じます。

切り替えの手順——わざと壊して確かめる

私が実際に進めている手順です。どれも10分ほどで済みます。

  1. 版を確かめる:claude --version が 2.1.295 以上か。無人ジョブを回す別のマシンがあるなら、そちらも見る(片方だけ古いと、設定が片方でしか効きません)
  2. フックを全部書き出す:settings.json の hooks を列挙し、1本ごとに「素通りしたら何が外に出るか」を1行で書く
  3. block にするものを決める:上の3つの問いを当てる。Stop 系と async は除外する
  4. ラッパーのガードを外す:「無ければ exit 0」があれば消す。"block" を付けるのはその後
  5. わざと壊して確かめる:スクリプトの名前を一時的に変えて、Claude Code に該当の操作を頼む。blocking because onFailure is "block" が出て操作が止まれば成功。名前を戻して、普段の操作が通ることも確かめる
  6. continue のままにしたものに記録を足す:素通りした事実が後から分かるように、フックの冒頭で実行ログを1行書く

5番は省略しないでください。今回の3番の例のように、設定ファイルを読むだけでは「効いているように見えて効いていない」状態を見分けられません。

取り違えやすい3点

「onFailure: block は、検査に落ちたら止める設定」

違います。検査に落ちたとき(=フックが意図して終了コード2を返したとき)は、onFailure と関係なく今までどおり止まります。onFailure が扱うのは、フックそのものが起動しない・時間切れ・想定外の終了コード・壊れた出力のときだけです。

「JSONで allow を返していれば、終了コードは何でもよい」

違います。公式ドキュメントは、0と2以外の終了コードは JSON で許可を出していても失敗扱いだと明記しています。JSON で判定を返すなら終了コードは0にそろえてください。"block" を付けたあとでこれを見落とすと、許可したつもりの操作が止まります。

「prompt フックや MCP のフックにも付けられる」

公式ドキュメントで onFailure が載っているのは command と http の項目表だけです(2026年10月12日に確認)。それ以外の種類で効くかは書かれていないので、使うなら自分の環境で上の5番の方法で確かめてからにしてください。

引用できる数字と条件のまとめ

項目

値

追加された版・日付

Claude Code 2.1.295・2026年10月8日

値

"continue"(既定)/"block"

対象のフック

command・http

効かないイベント

Stop・SubagentStop・TaskCompleted・TeammateIdle、async/asyncRewake のフック

PermissionRequest での動き

止めるのではなく拒否

存在しないスクリプトの終了コード(私の実測)

python3=2/sh=127/node=1

7通りの実測で素通りした数

3通り(うち1通りは block 付き)

私の環境で onFailure を書いていたフック

7本中0本

まとめ

onFailure: "block" は、フックを「検査に落ちたら止める」装置から、「検査が動かなかったときも止める」装置に変える1行です。ただし、Python は「ファイルが無い」を終了コード2で返すので付けなくても偶然止まることがあり、逆に「無ければ exit 0」のラッパーがあると付けても止まりません。設定ファイルを読むだけでは見分けられないので、わざと壊して確かめるところまでが1セットです。

どれを止める側に倒すかは、「素通りしたとき、取り消せないものが外に出るか」で決めます。私の環境では7本中3本がそれに当たりました。フックの基本的な書き方から確認したい場合は、こちらの入門記事が出発点になります。

Claude Code Hooks活用|品質チェックを自動化する方法
Claude CodeClaude Code Hooks活用|品質チェックを自動化する方法

参考にした情報

止めてはいけない側のフックの実例として、会話に貼ったスクショを Stop フックで自動保存する仕組みを解説しています。

Claude Code Stopフックで貼ったスクショを自動保存
Claude CodeClaude Code Stopフックで貼ったスクショを自動保存
この記事を読んでいるあなたへ無料プレゼント

Claudeのこの5つの設定、今すぐ見直した方がいい

共有・学習・入力・権限・委任。事故が起きるのはこの5つだけ(全28ページ)

2026年7月、Claudeの共有チャットがGoogle検索から読める状態になっていました。原因は設定そのものではなく、自分が過去に共有したものを覚えていないことでした。共有リンクの棚卸しから、学習をオフにしても残る例外条項、Claude Codeの権限モードまで、今日30分で確認できる形にまとめています。

  • 見落としやすい共有リストは3つある(3つ目は画面の下)
  • 学習をオフにしても残る、公式の例外条項
  • 権限モード6つの違いと、Shift+Tabでの切り替え方
  • 私が実際に禁止しているコマンド23行を全文公開

メールアドレス登録で他にも様々な資料を閲覧できます

「Sonnet 5.5」を、実務で比べてみた。Codexを使い始める前に、「絶対に」見直してほしい5つのこと「Opus 5.5」を、実務で比べてみた。Jevで得する仕事、損する仕事Astra と Fable 5.1、ベンチマークでは分からない「使い分け」。Fable 5.1、賢さは「どこ」に出たか。Workにしかできない仕事は、2つだけその太字、本物ですか3モデル実測|単価2倍が、いちばん安い+8

PDF 17点・合計440ページ + すぐ使えるzip素材 3点

どれも登録後の受け取りページから、まとめてダウンロードできます。

毎週配信の無料ニュースレター「AIネイティブ超研究」の購読特典です。メール登録後すぐ、受け取りページのご案内が届きます。そこにはこの資料に加えて、過去の特典もすべてまとめて置いてあります。あわせて、AI活用に関するお知らせやお役に立てそうなご案内をお送りすることがあります。解除はいつでも1クリック。

← 記事一覧に戻る

御社の業務に合わせたClaude Code導入支援

「AIツールを導入したが、現場で使われない」を終わらせる。
業務課題のヒアリングから設計、ハンズオン実践、運用定着まで一貫して支援します。

無料AI活用診断を受ける料金とサービス一覧を見る →
© 2025 Fyve Inc. All rights reserved.