Resources / Debugging Hook Failures
Guide 6 min read

Debugging Hook Failures

Troubleshoot common hook execution issues and learn best practices for reliable automation.

1

Common Failure Causes

Hooks fail for a handful of reasons:

  • A non-zero exit code: tests failing or lint errors
  • Exit code 127, "command not found": the command isn't installed or isn't on the agent's PATH
  • In before_doing: missing git credentials, no network, or uncommitted changes in the way
  • In before_review: the GitHub CLI isn't installed or signed in (gh auth login)
  • Taking longer than the 600-second (10-minute) timeout: make the commands faster rather than dropping checks
  • Empty variables: quote them, and export them when you test by hand
2

Reading the Error

The agent measures each hook's exit_code, output and duration_ms and sends them to Stride, for example as after_doing_result. If a result is missing, incomplete or failing, the call fails with HTTP 422, the task stays where it was, and the response says why:

{
  "error": "after_doing is a blocking hook and failed with exit code 1. Fix the issues and try again.",
  "hook": "after_doing",
  "required_format": {
    "after_doing_result": {
      "exit_code": 0,
      "output": "Hook execution output",
      "duration_ms": 1234
    }
  }
}

The Stride plugin for Claude Code reports a failing hook with the command that failed and its output, and the stride:hook-diagnostician agent turns that output into a plan for fixing it.

3

Testing Hooks Locally

.stride.md is a Markdown file, not a shell script, so you can't source it. To test a hook, export the variables it uses and run each line of its section one at a time in the project root, checking the exit code after each:

export TASK_IDENTIFIER="W1"
export TASK_TITLE="Try the hooks"
export HOOK_NAME="after_doing"
mix test
echo "exit code: $?"

Never print .stride_auth.md while you debug: it holds your token.

4

When a Hook Can't Be Fixed Now

If a hook keeps failing for a reason outside the task, the agent can give the task back with POST /api/tasks/:id/unclaim and a reason. The task returns to Ready for later.

A failing after_goal keeps the goal out of Done until a passing report arrives or the five-minute grace window ends.

5

Best Practices

  • Keep hooks fast, well under the 600-second limit
  • Put one command on each line: the agent stops at the first one that fails
  • Print meaningful output, so a failure explains itself
  • Leave a section empty when it has nothing to do
  • Check the review decision before merging or deploying in after_review
  • Test hooks by hand before relying on them

You're all set!

You've completed all the steps in this guide.