Skip to content

Fix report_error! demotions of typed errors into extra: (APP-5522) - #15298

Merged
acarl005 merged 1 commit into
masterfrom
app-5522-fix-report-error-demotions
Aug 19, 2026
Merged

Fix report_error! demotions of typed errors into extra: (APP-5522)#15298
acarl005 merged 1 commit into
masterfrom
app-5522-fix-report-error-demotions

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes APP-5522: report_error! call sites that demoted a real, typed error into extra: { "error" => ... } (or stringified it via anyhow!("{e}")/interpolated it into the grouping message), contradicting .agents/skills/logging-and-error-reporting/SKILL.md ("Choosing the form" rule 1 and the Anti-patterns block). Reported by Andrew Carlson via Slack: the flagged line.

The demotions were introduced by #13483 (the mass log::error!report_error! migration), which also added the skill that forbids them. A sibling task is separately hardening the review-prompting that let this class of regression through; this PR is the code cleanup only — it does not touch anything under .agents/skills/.

Note on the originally-flagged line

An unrelated concurrent PR (#15287, merged just before this branch was cut) already fixed the two spawn_tui_driver draw-error sites in crates/warpui_core/src/runtime/mod.rs (the one the complaint linked, plus the invalidation-callback twin), wrapping them in .context() and adding ReportErrorLogMode::OncePerRun. This PR leaves those two alone (verified the landed form is correct) and instead fixes the third, still-broken site in the same file — the terminal-event reader — which #15287 didn't touch.

Categories fixed

  • Category A (typed Error stuffed into extra: only): crates/warpui_core/src/runtime/mod.rs (event reader), crates/http_server/src/lib.rs, crates/warpui_core/src/core/app.rs, crates/warpui_core/src/integration/mod.rs, crates/warpui_extras/src/user_preferences/registry_backed.rs, app/src/ai/geap_credentials.rs.
  • Category B (String/non-Error extra: family): upgraded interim anyhow!("{e}") wraps where a Result was in hand (commit.rs, default_terminal/mod.rs), removed a double-report in the Docker sandbox environment-prep path (the inner path already reports the typed error — the outer sink now just logs), and switched terminal_pane.rs's remote-child launch failure to report the typed error with conversation_id kept as incidental extra:. Also upgraded the two notification-permission "unknown error" sites (terminal/view.rs, workspace/view.rs x2) to treat the message as the payload instead of extra:.
  • Category C (message interpolation): crates/warp_tui/src/terminal_session_view.rs — stopped putting {error} in the grouped message for the two settings-persistence paths.
  • Category D (anyhow!("{e}") stringify sites, defeats is_actionable): rewrote to preserve the typed chain via anyhow::Error::new(e).context(..) (or e.context(..) when already anyhow, or &e when the value is still needed afterward and can't be cloned). Two Display-only, unregistered error types (LoadGeapCredentialsError, PrepareRemoteChildLaunchError) and one unrelated Display-only type discovered along the way (HexColorError) were upgraded to real thiserror::Error types so they can be reported typed instead of stringified — see the review-fix note below on keeping LoadGeapCredentialsError's Display static.

Left alone (verified, not violations)

  • local_tty/terminal_manager.rs:519JoinHandle::join()'s error is Box<dyn Any>, not std::error::Error.
  • app/src/pane_group/child_agent/mod.rs:222error_message is a request field (String), not a caught Error; static message + incidental extra: is correct under rule 4.
  • fetch_conversation.rs:99, code_diff_view.rs:1048 — the wrapped functions (materialize_tasks_to_yaml, restore_diff_base) already return Result<_, String>; there's no typed chain to preserve, so the existing anyhow!("{e}") form is already correct.
  • crates/warpui/src/windowing/winit/event_loop/mod.rs:1952SoftKeyboardManager::new's error is JsValue, not std::error::Error (and not Send/Sync).
  • The five Category E lookalikes named in the issue (image.rs:292, cache_setup.rs:144, response_stream.rs:693/:708, experiments/mod.rs:302/:321) were re-checked and are legitimately incidental data, not demotions.

Review fixes (round 2)

An adversarial review of the first version of this PR found that a form-correct rewrite can still ship user content to Sentry if the now-preserved Display/Debug itself carries it — the no-secrets/no-PII rule outranks form correctness. Four findings, all now fixed on this branch:

  1. LoadGeapCredentialsError's derived Display interpolated detail, which carries the raw Google STS/IAM response body. Its messages are now static; detail/status stay on the type for user_facing() (which already never echoed them), but Display no longer does either. Updated the now-stale test comment that asserted no Display existed.
  2. file_outline/native.rs:86 — I'd classified this as a harmless non-Error (true), but the retained anyhow!("{e:?}") was still uploading the undelivered outline map's Debug, which includes source symbol names and comments. Now a static message, throttled with OncePerRun since it can recur once per outline build.
  3. The deferred wasm SoftKeyboardInput send-failure site (event_loop/mod.rs:1940) is now fixed rather than deferred: EventLoopClosed<CustomEvent> does implement std::error::Error, and CustomEvent is Send + Sync, so it's reported typed (anyhow::Error::new(e).context(..), static Display) instead of via {e:?}, which could otherwise upload the user's typed keyboard text.
  4. response_stream.rs's conversion-failure path reported the same error twice — once directly, then again via report_request_failure right after. Removed the standalone report; report_request_failure is now the single sink.

Linked Issue

  • APP-5522 (this is a factory:wilson-labeled hygiene issue, not ready-to-spec/ready-to-implement)

Testing

No behavior change for users — this only changes what gets reported to Sentry and how it's classified/grouped/redacted. Verified with:

  • ./script/format --check — clean.

  • cargo clippy --all-targets --tests -- -D warnings scoped to every touched package and its relevant feature combinations (warp, warp --features local_tty, ai, warp_core, http_server, warpui_extras, warpui_core --features tui,integration_tests, warp_tui, warpui) — clean.

  • cargo check on all of the above — clean.

  • cargo nextest run on all of the above — all passing except a handful of pre-existing, environment-dependent failures unrelated to this change (missing bundled SVG assets, a sandboxed nsc command being denied, a WARP_API_KEY env var leaking into a CLI-parsing test, and font-layout bidirectional-text assertions); none touch files this PR modifies.

  • Two Windows-only files (registry_backed.rs, single_instance_manager.rs) could not be compiled in this Linux sandbox (no Windows cross toolchain, and no permission to add a Rust target); reviewed by hand against each dependency's documented trait impls instead. The wasm-only event_loop.rs fix (finding 3 above) is likewise unverified by a wasm build for the same reason — implemented per the review's confirmed analysis of CustomEvent's Send + Sync bound.

  • Did not run the full ./script/presubmit (workspace-wide clippy/tests) due to sandbox time/disk constraints; ran the equivalent checks scoped to every touched crate instead.

  • I have manually tested my changes locally with ./script/run (not applicable — no UI change; verified via targeted cargo check/clippy/nextest above)

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

Rewrites report_error! call sites that demoted a real, typed error into
extra: (or stringified it via anyhow!("{e}")) into the skill-prescribed
form, per .agents/skills/logging-and-error-reporting/SKILL.md rule 1 and
the Anti-patterns block. This restores is_actionable() classification for
the affected errors.

Categories fixed:
- Category A (7 sites): typed Error stuffed into extra: only. Two of the
  seven (runtime/mod.rs's timed-repaint site and the invalidation-callback
  throttle) were already fixed upstream by #15287; the event-reader twin
  in the same file was not and is fixed here.
- Category B (String/non-Error extra: family): upgraded interim
  anyhow!("{e}") wraps where a Result was in hand, removed a double-report
  in the Docker sandbox environment-prep path (the inner path already
  reports the typed error), and switched terminal_pane.rs's remote-child
  launch failure to report the typed error with conversation_id kept as
  incidental extra:.
- Category C (2 sites): stopped interpolating the error into the grouped
  message in the TUI settings-persistence paths.
- Category D (anyhow!("{e}") stringify sites): rewrote to preserve the
  typed chain via anyhow::Error::new(e).context(..) (or e.context(..) when
  already anyhow, or &e when the value is still needed afterward and can't
  be cloned). Two Display-only, unregistered error types
  (LoadGeapCredentialsError, PrepareRemoteChildLaunchError) and one
  Display-only type unrelated to this PR's scope (HexColorError) were
  upgraded to real thiserror::Error types so they can be reported typed
  instead of stringified.

Left alone (confirmed not violations, or String/non-Error payloads where
rule 4 already applies):
- local_tty/terminal_manager.rs:519 - JoinHandle::join()'s error is
  Box<dyn Any>, not std::error::Error.
- app/src/pane_group/child_agent/mod.rs:222 - error_message is a request
  field (String), not a caught Error; static + incidental extra: is fine
  under rule 4.
- fetch_conversation.rs:99, code_diff_view.rs:1048 - the wrapped functions
  (materialize_tasks_to_yaml, restore_diff_base) already return
  Result<_, String>; no typed chain to preserve.
- file_outline/native.rs:86 - oneshot::Sender::send's Err returns the
  unsent payload (a HashMap), not an error.
- event_loop/mod.rs:1952 - SoftKeyboardManager::new's error is JsValue,
  not std::error::Error (and not Send/Sync).
- The five Category E lookalikes called out in the issue (image.rs:292,
  cache_setup.rs:144, response_stream.rs:693/708,
  experiments/mod.rs:302/321) were re-verified and are legitimately
  incidental data, not demotions.

Deferred:
- event_loop/mod.rs:1940 (wasm-only SoftKeyboardInput event send failure)
  is a real std::error::Error (EventLoopClosed<CustomEvent>), but
  anyhow::Error::new requires the wrapped type to be Send + Sync + 'static
  and this is wasm-only code this sandbox cannot cross-compile to verify.
  Left as-is rather than risk an unverified break.
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

This PR was generated with Warp.

Comment @warp-factory on this PR to send it follow-up work.

View run View conversation

@acarl005
acarl005 marked this pull request as ready for review August 19, 2026 00:48
@acarl005 acarl005 self-assigned this Aug 19, 2026
@acarl005
acarl005 merged commit d68a638 into master Aug 19, 2026
48 checks passed
@acarl005
acarl005 deleted the app-5522-fix-report-error-demotions branch August 19, 2026 01:11
@warp-agent-staging
warp-agent-staging Bot requested a review from acarl005 August 19, 2026 01:16
acarl005 pushed a commit that referenced this pull request Aug 19, 2026
…merge race (APP-5522) (#15300)

## Description

**This closes a live Sentry data-exposure path, not ordinary hygiene.**
#15298 (APP-5522) merged at `d68a638e` without its review-round fixes —
the review found and I fixed four issues, but the fix commit
(`949b5a683`) landed on the PR branch about two and a half minutes after
#15298 was already merged, so it never reached `master`. As a result,
since `d68a638e` landed on `master`, the following have been shipping to
Sentry:

- **Raw Google STS/IAM response bodies.**
`crates/ai/src/geap_credentials.rs`'s
`LoadGeapCredentialsError::Display` interpolates `detail`, and
`app/src/ai/geap_credentials.rs:346` reports that error as the payload,
so every Gemini Enterprise credential-mint failure has been uploading
the provider's raw response text to Sentry.
- **The user's typed keyboard input, on mobile WASM.**
`crates/warpui/src/windowing/winit/event_loop/mod.rs`'s
soft-keyboard-input send-failure path stringifies the failed event via
`{e:?}`, which can be `SoftKeyboardInput::TextInserted(<what the user
typed>)`.
- **Source symbol names and comments from the user's codebase.**
`crates/ai/src/index/file_outline/native.rs` debug-prints the
undelivered outline map (file/symbol names, doc comments) when the
background-thread handoff fails.

**Anyone with Sentry access should decide whether events captured since
`d68a638e` landed need scrubbing.** I don't have visibility into the
Sentry project to check volume or scope this myself.

This PR is `949b5a683` — the exact five-file review-fix commit from
#15298 — cherry-picked cleanly onto current `master` (verified: the
cherry-pick applied with no conflicts, and I re-diffed all five files
against `master` after picking to confirm they match the intended
post-review state and that nothing else moved underneath in the
meantime).

### What changed (unchanged from the original review fix)
- `crates/ai/src/geap_credentials.rs` /
`app/src/ai/geap_credentials_tests.rs`: `LoadGeapCredentialsError`'s
three `#[error(..)]` messages are now static — no `detail`, no `status`
interpolation. `detail`/`status` stay on the type for `user_facing()`'s
use (which never echoed them either); updated the test comment that
asserted no `Display` existed.
- `crates/ai/src/index/file_outline/native.rs`: the oneshot-send failure
now reports a static message instead of `{e:?}` on the undelivered
outline map, throttled with `ReportErrorLogMode::OncePerRun` since it
can recur once per outline build.
- `crates/warpui/src/windowing/winit/event_loop/mod.rs`: the
`SoftKeyboardInput` send failure now reports the error typed —
`report_error!(anyhow::Error::new(e).context("Failed to send
SoftKeyboardInput event"))` — whose `Display` is static, instead of
`{e:?}` on the undelivered event.
- `app/src/ai/blocklist/controller/response_stream.rs`: removed a
double-report of the same request-conversion failure (`report_error!`
immediately followed by `report_request_failure` reporting it again);
`report_request_failure` is now the single sink.

## Linked Issue
- Follow-up to
[APP-5522](https://linear.app/warpdotdev/issue/APP-5522/fix-report-error-demotions-of-typed-errors-into-extra-and-related-form)
and #15298 (merged without this commit).

## Testing
Re-verified after cherry-picking, on top of current `master`:
- `./script/format --check` — clean.
- `cargo check` / `cargo clippy --all-targets --tests -- -D warnings` on
`ai`, `warp`, `warpui` — clean.
- `cargo nextest run`: the 35 `geap`/`response_stream` tests and the
full `ai` crate suite (364 tests) pass. `warpui`'s only failures are 3
pre-existing font-layout bidirectional-text assertions unrelated to
`event_loop.rs` (same failures reproduced on the original PR branch
before this change).
- The wasm-only `event_loop.rs` line and the two Windows-only files from
the original PR aren't touched further here beyond what's in
`949b5a683`; still unverified by a wasm/Windows build in this sandbox
(no cross toolchain, no permission to add a Rust target) — same caveat
as on #15298.
- Did not re-run the full workspace `./script/presubmit`; ran the
equivalent scoped checks above instead.

- [ ] I have manually tested my changes locally with `./script/run` (not
applicable — no UI change; verified via targeted `cargo
check`/`clippy`/`nextest` above)

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

<!-- warp:pr-description-artifacts start -->
<!-- warp:pr-description-artifacts end -->

---------

Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>
acarl005 pushed a commit that referenced this pull request Aug 19, 2026
## Description

Follow-up to
[APP-5522](https://linear.app/warpdotdev/issue/APP-5522/fix-report-error-demotions-of-typed-errors-into-extra-and-related-form)
/ #15298. A code-quality review of that PR found that several comments
it added (in `ab67dc79`, which merged to `master`) narrate what the code
already makes evident, or repeat the same explanation verbatim at more
than one call site — both against `AGENTS.md`'s comment rules. This PR
removes exactly those comments; no code changes.

Removed:
- `app/src/ai/blocklist/controller/response_stream.rs`: the "own the
converted error" ownership rationale ahead of `let converted_error =
anyhow::Error::new(e);`.
- `app/src/terminal/view/docker_sandbox/mod.rs`: the
double-report-avoidance note on the outer sink's `Err(err)` arm (the
sink itself, now just a `log::warn!`, makes this self-evident without
narration).
- `crates/ai/src/index/full_source_code_embedding/codebase_index.rs` and
`crates/ai/src/index/full_source_code_embedding/sync_client.rs` (two
call sites): three near-identical "reported borrowed to keep it typed"
comments explaining the same `report_error!(&err)` pattern — kept once
isn't warranted here either, since each is a one-line, self-explanatory
call.

Not removed, and why: `crates/warpui_core/src/runtime/mod.rs`'s "The
reader runs on a dedicated thread…" comment appears in the `ab67dc79`
diff as a `-`/`+` pair, but that's a reformatting artifact — the closure
body was rewrapped from `move || loop { .. }` to `move || { loop { .. }
} }` (rustfmt), which shifted every line's indentation including this
pre-existing, unchanged comment. It wasn't added by this change and
isn't a new violation, so I left it alone.

## Linked Issue
- Follow-up to APP-5522 / #15298 (comment-only, no behavior change).

## Testing
Comment-only diff; no code changed. Verified:
- `./script/format --check` — clean.
- `cargo check` / `cargo clippy --all-targets --tests -- -D warnings` on
`ai`, `warp` — clean.
- `cargo nextest run`: full `ai` crate suite (364 tests) and the
`response_stream`/`docker_sandbox` tests in `warp` (15 tests) pass.

- [ ] I have manually tested my changes locally with `./script/run` (not
applicable — comment-only change)

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

<!-- warp:pr-description-artifacts start -->
<!-- warp:pr-description-artifacts end -->

Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>
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.

1 participant