Skip to content

Handle claude code StopFailure hook#13784

Merged
seemeroland merged 7 commits into
masterfrom
roland/claude-code-stop-failure
Jul 16, 2026
Merged

Handle claude code StopFailure hook#13784
seemeroland merged 7 commits into
masterfrom
roland/claude-code-stop-failure

Conversation

@seemeroland

Copy link
Copy Markdown
Contributor

Description

Resolves https://linear.app/warpdotdev/issue/REMOTE-1997/oz-shows-claude-code-run-as-running-after-anthropic-api-500-error

Handle the StopFailure hook from Claude Code. We use the error type to map to Failed or Error status.

There is technically a race between this and scanning for runtime_error_patterns. But most of the time this will win since it's instant, and the scan for runtime_error_patterns will be suppressed. In the event that runtime_error_patterns scanning happens first, we'll end up with a duplicate task status update from the hook which is okay.

Testing

  • I have manually tested my changes locally with ./script/run

Tested locally with warpdotdev/claude-code-warp#73

Run claude code with invalid model and using local plugin build:
ANTHROPIC_MODEL=claude-4-8-opus-high claude --plugin-dir ~/claude-code-warp/plugins/warp

Send a query, see a log in warp

12:45:03.758 [INFO] [warp::terminal::model::ansi] Received OSC 777 notification: title=Some("warp://cli-agent"), body={"v":1,"agent":"claude","event":"stop_failure","session_id":"8c574469-befe-4e9a-802a-6e3350ab2f5a","cwd":"/Users/rolandhuang","project":"rolandhuang","query":"here is another test","response":"There's an issue with the selected model (claude-4-8-opus-high). It may not exist or you may not have access to it. Run /model to pick a different model.","error_type":"model_not_found","transcript_path":"/Users/rolandhuang/.claude/projects/-Users-rolandhuang/8c574469-befe-4e9a-802a-6e3350ab2f5a.jsonl"}

@cla-bot cla-bot Bot added the cla-signed label Jul 15, 2026
@seemeroland
seemeroland marked this pull request as ready for review July 15, 2026 19:51
@seemeroland
seemeroland requested a review from liliwilson July 15, 2026 19:51
@oz-for-oss

oz-for-oss Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@seemeroland

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@seemeroland
seemeroland requested a review from harryalbert July 15, 2026 19:52

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds Claude Code stop_failure event parsing, introduces a CLI session Failed state, maps that state into task updates, and suppresses duplicate runtime-pattern failures when the plugin reports failure first.

Concerns

  • StopFailure does not persist the failed turn's query/response into session_context, so user-facing notifications and conversation surfaces that read context can show fallback or empty details despite the event including the data.
  • The task-state mapping leaves user-actionable Claude Code request failures such as model_not_found, invalid_request, and max_output_tokens classified as Error, including the invalid-model scenario described in this PR.
  • For this user-facing status/notification change, please include screenshots or a screen recording demonstrating the failed Claude Code run moving to the expected failed/error state end to end.

Verdict

Found: 0 critical, 3 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/terminal/cli_agent_sessions/mod.rs
Comment on lines +559 to +564
let task_state = match error_type.as_deref() {
Some("authentication_failed" | "oauth_org_not_allowed" | "billing_error") => {
AgentTaskState::Failed
}
_ => AgentTaskState::Error,
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] Classify user-actionable request failures as Failed; with the current _ arm, the invalid-model case from the PR description reports as a provider/Warp Error instead of a user-fixable failure.

Suggested change
let task_state = match error_type.as_deref() {
Some("authentication_failed" | "oauth_org_not_allowed" | "billing_error") => {
AgentTaskState::Failed
}
_ => AgentTaskState::Error,
};
let task_state = match error_type.as_deref() {
Some(
"authentication_failed"
| "oauth_org_not_allowed"
| "billing_error"
| "invalid_request"
| "model_not_found"
| "max_output_tokens",
) => AgentTaskState::Failed,
_ => AgentTaskState::Error,
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list is intentional. The other error categories mean warp configured something incorrectly

"could not be refreshed",
// Generically check for invalid request errors.
// Keep this last so more specific patterns can be matched first.
"\"type\": \"invalid_request_error\"",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex doesn't have an equivalent hook. We add this runtime pattern match to fix this run not properly being marked as errored https://oz.staging.warp.dev/runs/019f6324-bb99-70fa-aa53-d200dd806dca

@seemeroland

Copy link
Copy Markdown
Contributor Author

/oz-review

@oz-for-oss

oz-for-oss Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@seemeroland

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds support for Claude Code StopFailure hook events by parsing stop_failure, introducing a failed CLI session status, updating notifications, suppressing duplicate runtime-pattern failures, and syncing terminal task state as failed or errored.

Concerns

  • model_not_found is classified as ERROR, but the PR’s own test case uses an invalid selected model and Claude Code documents that as a request/configuration error. That will mark a user-actionable model selection problem as a system/provider error instead of a failed task.
  • This is a user-facing behavior change: it changes the displayed Oz task status and failure notification flow. For this user-facing change, please include screenshots or a screen recording demonstrating it working end to end.
  • No security findings.
  • No approved or repository spec context was provided, so there is no spec drift to report.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment on lines +559 to +564
let task_state = match error_type.as_deref() {
Some("authentication_failed" | "oauth_org_not_allowed" | "billing_error") => {
AgentTaskState::Failed
}
_ => AgentTaskState::Error,
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] model_not_found is a user-actionable bad model selection (the PR’s testing reproduces this with an invalid ANTHROPIC_MODEL), so mapping it through _ => Error misclassifies the task as a system/provider error.

Suggested change
let task_state = match error_type.as_deref() {
Some("authentication_failed" | "oauth_org_not_allowed" | "billing_error") => {
AgentTaskState::Failed
}
_ => AgentTaskState::Error,
};
let task_state = match error_type.as_deref() {
Some(
"authentication_failed"
| "oauth_org_not_allowed"
| "billing_error"
| "model_not_found",
) => AgentTaskState::Failed,
_ => AgentTaskState::Error,
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect. Warp is responsible for setting the model and validating it before starting the worker

#13784 (comment)

@liliwilson liliwilson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, really awesome that claude supports this

@seemeroland
seemeroland merged commit a5242e6 into master Jul 16, 2026
28 checks passed
@seemeroland
seemeroland deleted the roland/claude-code-stop-failure branch July 16, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants