Fix report_error! demotions of typed errors into extra: (APP-5522) - #15298
Merged
Conversation
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.
Contributor
Author
|
This PR was generated with Warp. Comment |
acarl005
marked this pull request as ready for review
August 19, 2026 00:48
acarl005
approved these changes
Aug 19, 2026
This was referenced Aug 19, 2026
Merged
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
Fixes APP-5522:
report_error!call sites that demoted a real, typed error intoextra: { "error" => ... }(or stringified it viaanyhow!("{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_driverdraw-error sites incrates/warpui_core/src/runtime/mod.rs(the one the complaint linked, plus the invalidation-callback twin), wrapping them in.context()and addingReportErrorLogMode::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
Errorstuffed intoextra: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.extra:family): upgraded interimanyhow!("{e}")wraps where aResultwas 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 switchedterminal_pane.rs's remote-child launch failure to report the typed error withconversation_idkept as incidentalextra:. Also upgraded the two notification-permission "unknown error" sites (terminal/view.rs,workspace/view.rsx2) to treat the message as the payload instead ofextra:.crates/warp_tui/src/terminal_session_view.rs— stopped putting{error}in the grouped message for the two settings-persistence paths.anyhow!("{e}")stringify sites, defeatsis_actionable): rewrote to preserve the typed chain viaanyhow::Error::new(e).context(..)(ore.context(..)when alreadyanyhow, or&ewhen 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 realthiserror::Errortypes so they can be reported typed instead of stringified — see the review-fix note below on keepingLoadGeapCredentialsError'sDisplaystatic.Left alone (verified, not violations)
local_tty/terminal_manager.rs:519—JoinHandle::join()'s error isBox<dyn Any>, notstd::error::Error.app/src/pane_group/child_agent/mod.rs:222—error_messageis a request field (String), not a caughtError; static message + incidentalextra: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 returnResult<_, String>; there's no typed chain to preserve, so the existinganyhow!("{e}")form is already correct.crates/warpui/src/windowing/winit/event_loop/mod.rs:1952—SoftKeyboardManager::new's error isJsValue, notstd::error::Error(and notSend/Sync).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/Debugitself carries it — the no-secrets/no-PII rule outranks form correctness. Four findings, all now fixed on this branch:LoadGeapCredentialsError's derivedDisplayinterpolateddetail, which carries the raw Google STS/IAM response body. Its messages are now static;detail/statusstay on the type foruser_facing()(which already never echoed them), butDisplayno longer does either. Updated the now-stale test comment that asserted noDisplayexisted.file_outline/native.rs:86— I'd classified this as a harmless non-Error(true), but the retainedanyhow!("{e:?}")was still uploading the undelivered outline map'sDebug, which includes source symbol names and comments. Now a static message, throttled withOncePerRunsince it can recur once per outline build.SoftKeyboardInputsend-failure site (event_loop/mod.rs:1940) is now fixed rather than deferred:EventLoopClosed<CustomEvent>does implementstd::error::Error, andCustomEventisSend + Sync, so it's reported typed (anyhow::Error::new(e).context(..), staticDisplay) instead of via{e:?}, which could otherwise upload the user's typed keyboard text.response_stream.rs's conversion-failure path reported the same error twice — once directly, then again viareport_request_failureright after. Removed the standalone report;report_request_failureis now the single sink.Linked Issue
factory:wilson-labeled hygiene issue, notready-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 warningsscoped 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 checkon all of the above — clean.cargo nextest runon all of the above — all passing except a handful of pre-existing, environment-dependent failures unrelated to this change (missing bundled SVG assets, a sandboxednsccommand being denied, aWARP_API_KEYenv 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-onlyevent_loop.rsfix (finding 3 above) is likewise unverified by a wasm build for the same reason — implemented per the review's confirmed analysis ofCustomEvent'sSend + Syncbound.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 targetedcargo check/clippy/nextestabove)Agent Mode
CHANGELOG-NONE