From 4c8bdcc38443182d8bc3908d96cce0b762cd18cb Mon Sep 17 00:00:00 2001 From: Oz Date: Fri, 17 Jul 2026 21:31:39 +0000 Subject: [PATCH 1/2] Demote non-actionable report_error! calls to log::warn! in terminal model Audits every `report_error!` call in the terminal model, session, history, and writeable_pty files per the logging-and-error-reporting skill, and demotes the ones that fire on external/expected/gracefully-handled conditions (channel teardown sends, temp-file cleanup, user/enterprise regex compile failures, corrupted or unexpected DCS input, invalid shell names, hostname lookup fallback, remote history read failure, bootstrap path-conversion fallback) to `log::warn!` so they no longer create Sentry issues. Genuine invariant/"should never happen" guards (ANSI handler contract stubs, bootstrap stage-machine violations, block-height/gap invariants, prompt-marker routing invariants, docker-sandbox routing-drift guard, the registered ReadHistoryContentsError sink, etc.) are kept as `report_error!`. Co-Authored-By: Warp --- app/src/terminal/model/kitty.rs | 7 +------ app/src/terminal/model/secrets.rs | 7 ++----- app/src/terminal/model/session.rs | 10 +++++----- .../command_executor/in_band_command_executor.rs | 7 +++---- app/src/terminal/model/terminal_model.rs | 14 +++++++------- app/src/terminal/writeable_pty/command_history.rs | 3 +-- app/src/terminal/writeable_pty/pty_controller.rs | 4 +--- 7 files changed, 20 insertions(+), 32 deletions(-) diff --git a/app/src/terminal/model/kitty.rs b/app/src/terminal/model/kitty.rs index 282658ca3ed..1acf1c78e2e 100644 --- a/app/src/terminal/model/kitty.rs +++ b/app/src/terminal/model/kitty.rs @@ -8,8 +8,6 @@ use base64::Engine; use flate2::read::ZlibDecoder; use pathfinder_geometry::vector::Vector2F; use rand::Rng; -#[cfg(feature = "local_fs")] -use warp_errors::report_error; use warpui::assets::asset_cache::Asset; use warpui::image_cache::{ resize_dimensions, CustomHeaderCreationError, CustomImageFormat, CustomImageHeader, FitType, @@ -764,10 +762,7 @@ fn read_file(decoded_payload: Vec, is_temp: bool) -> Result, Invalid fn safe_delete_temp_file(path: &str) { if is_path_in_temp_dir(path) && path.contains("tty-graphics-protocol") { if let Err(err) = fs::remove_file(path) { - report_error!( - anyhow::Error::new(err).context("Failed to delete kitty temporary file"), - extra: { "path" => %path } - ); + log::warn!("Failed to delete kitty temporary file (path = {path}): {err:#}"); } } } diff --git a/app/src/terminal/model/secrets.rs b/app/src/terminal/model/secrets.rs index 24e99138aee..594749d485b 100644 --- a/app/src/terminal/model/secrets.rs +++ b/app/src/terminal/model/secrets.rs @@ -10,7 +10,6 @@ use itertools::Itertools; use lazy_static::lazy_static; use parking_lot::Mutex; use rangemap::{RangeInclusiveMap, StepLite}; -use warp_errors::report_error; use warpui::elements::SecretRange; use warpui::EntityId; @@ -377,8 +376,7 @@ pub fn set_user_and_enterprise_secret_regexes<'a>( let dfas = match RegexDFAs::new_many(&all_secrets, false, true) { Ok(dfas) => dfas, Err(err) => { - report_error!(anyhow::Error::new(err) - .context("Failed to construct new RegexDFA with combined secrets")); + log::warn!("Failed to construct new RegexDFA with combined secrets: {err:#}"); return; } }; @@ -392,8 +390,7 @@ pub fn set_user_and_enterprise_secret_regexes<'a>( }, }, Err(err) => { - report_error!(anyhow::Error::new(err) - .context("Failed to construct new Regex with combined secrets")); + log::warn!("Failed to construct new Regex with combined secrets: {err:#}"); return; } }; diff --git a/app/src/terminal/model/session.rs b/app/src/terminal/model/session.rs index 97d6a062834..e1b664f4a3c 100644 --- a/app/src/terminal/model/session.rs +++ b/app/src/terminal/model/session.rs @@ -528,9 +528,9 @@ impl Sessions { if let Some(in_band_command_output_tx) = self.in_band_command_output_tx_map.get(&session_id) { if let Err(e) = in_band_command_output_tx.try_send(event) { - report_error!(anyhow::Error::new(e).context( - "Failed to send ExecutedExecutorCommandEvent to InBandCommandExecutor" - )); + log::warn!( + "Failed to send ExecutedExecutorCommandEvent to InBandCommandExecutor: {e:#}" + ); } } } @@ -740,7 +740,7 @@ impl SessionInfo { } } Err(e) => { - warp_errors::report_error!(e); + log::warn!("Failed to get local hostname when determining session type: {e:#}"); BootstrapSessionType::Local } } @@ -1560,7 +1560,7 @@ impl Session { ) } CommandExitStatus::Failure => { - report_error!("Failed to parse history file from file"); + log::warn!("Failed to parse history file from file"); None } } diff --git a/app/src/terminal/model/session/command_executor/in_band_command_executor.rs b/app/src/terminal/model/session/command_executor/in_band_command_executor.rs index 633d2647654..47e0bb37919 100644 --- a/app/src/terminal/model/session/command_executor/in_band_command_executor.rs +++ b/app/src/terminal/model/session/command_executor/in_band_command_executor.rs @@ -10,7 +10,6 @@ use async_trait::async_trait; use parking_lot::{Mutex, MutexGuard}; use warp_completer::completer::{CommandExitStatus, CommandOutput}; use warp_core::command::ExitCode; -use warp_errors::report_error; use warp_terminal::model::Point; use warp_util::on_cancel::OnCancelFutureExt; use warpui::r#async::block_on; @@ -226,9 +225,9 @@ impl InBandCommandExecutor { } }; if let Err(error) = output_tx.try_send(command_output) { - report_error!(anyhow::Error::new(error).context( - "Error occurred when sending generator command output" - )); + log::warn!( + "Error occurred when sending generator command output: {error}" + ); } } } diff --git a/app/src/terminal/model/terminal_model.rs b/app/src/terminal/model/terminal_model.rs index 01ce3909220..bfd340d2b0d 100644 --- a/app/src/terminal/model/terminal_model.rs +++ b/app/src/terminal/model/terminal_model.rs @@ -3016,7 +3016,7 @@ impl ansi::Handler for TerminalModel { // Not being able to read the value should not cause a full-app crash. Instead, // bootstrapping should fail in the same way that it would if the DCS message // were otherwise corrupted. - report_error!("Received bootstrap message with no pending session info."); + log::warn!("Received bootstrap message with no pending session info."); return; } }; @@ -3162,9 +3162,9 @@ impl ansi::Handler for TerminalModel { uname: data.uname, })) } - None => report_error!( - "Received invalid shell name in init_subshell", - extra: { "shell" => %data.shell } + None => log::warn!( + "Received invalid shell name in init_subshell: {}", + data.shell ), } } @@ -3186,9 +3186,9 @@ impl ansi::Handler for TerminalModel { )) } None => { - report_error!( - "Received invalid shell name in SourcedRCFileForWarpValue", - extra: { "shell" => %data.shell } + log::warn!( + "Received invalid shell name in SourcedRCFileForWarpValue: {}", + data.shell ); } } diff --git a/app/src/terminal/writeable_pty/command_history.rs b/app/src/terminal/writeable_pty/command_history.rs index 0497ea080b9..5393dc18b56 100644 --- a/app/src/terminal/writeable_pty/command_history.rs +++ b/app/src/terminal/writeable_pty/command_history.rs @@ -2,7 +2,6 @@ use std::sync::mpsc::SyncSender; use std::sync::Arc; use parking_lot::FairMutex; -use warp_errors::report_error; use warpui::{AppContext, ModelHandle, SingletonEntity}; use crate::persistence::{ModelEvent, StartedCommandMetadata}; @@ -69,7 +68,7 @@ pub fn update_command_history( .spawn(async move { // Sending over a sync sender can block the current thread, so we do this async. if let Err(e) = sender_clone.send(insert_command_event) { - report_error!(anyhow::Error::new(e).context("Error sending ModelEvent")); + log::warn!("Error sending ModelEvent: {e:#}"); } }) .detach(); diff --git a/app/src/terminal/writeable_pty/pty_controller.rs b/app/src/terminal/writeable_pty/pty_controller.rs index dc6052742f1..6265628c185 100644 --- a/app/src/terminal/writeable_pty/pty_controller.rs +++ b/app/src/terminal/writeable_pty/pty_controller.rs @@ -5,8 +5,6 @@ use std::sync::Arc; use async_channel::{Receiver, Sender}; use parking_lot::FairMutex; use thiserror::Error; -#[cfg(feature = "local_fs")] -use warp_errors::report_error; use warp_util::path::ShellFamily; use warpui::r#async::block_on; use warpui::{Entity, ModelContext, ModelHandle, SingletonEntity}; @@ -429,7 +427,7 @@ impl PtyController { self.source_bootstrap_script(path, shell_type, ctx); } else { self.write_terminating_bootstrap_bytes(ctx); - report_error!("Could not convert bootstrap script file path to str"); + log::warn!("Could not convert bootstrap script file path to str"); } self.bootstrap_file = Some(file); From 128ab67dae47b09ef807266b8aea14310b4b24a4 Mon Sep 17 00:00:00 2001 From: Oz Date: Fri, 17 Jul 2026 21:57:26 +0000 Subject: [PATCH 2/2] Use safe_warn! for demoted warns that carry sensitive values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses review feedback: warn-level breadcrumbs are uploaded to Sentry on crash-reporting builds, so the demoted warns that include user/enterprise secret regex patterns (secrets.rs), a user-controlled temp-file path (kitty.rs), and a DCS-supplied shell name (terminal_model.rs init_subshell + sourced_rc_file) now use `safe_warn!` — the `safe:` arm is a static, breadcrumb- safe message and the sensitive detail only appears in the dogfood-only `full:` arm. Co-Authored-By: Warp --- app/src/terminal/model/kitty.rs | 7 ++++++- app/src/terminal/model/secrets.rs | 11 +++++++++-- app/src/terminal/model/terminal_model.rs | 16 ++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/app/src/terminal/model/kitty.rs b/app/src/terminal/model/kitty.rs index 1acf1c78e2e..6e629f1e230 100644 --- a/app/src/terminal/model/kitty.rs +++ b/app/src/terminal/model/kitty.rs @@ -16,6 +16,8 @@ use warpui::image_cache::{ use warpui::util::{parse_i32, parse_u32}; use super::escape_sequences::C1; +#[cfg(feature = "local_fs")] +use crate::safe_warn; /// Actions specified by the [Kitty Image Protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) #[derive(Debug, Clone)] @@ -762,7 +764,10 @@ fn read_file(decoded_payload: Vec, is_temp: bool) -> Result, Invalid fn safe_delete_temp_file(path: &str) { if is_path_in_temp_dir(path) && path.contains("tty-graphics-protocol") { if let Err(err) = fs::remove_file(path) { - log::warn!("Failed to delete kitty temporary file (path = {path}): {err:#}"); + safe_warn!( + safe: ("Failed to delete kitty temporary file"), + full: ("Failed to delete kitty temporary file (path = {path}): {err:#}") + ); } } } diff --git a/app/src/terminal/model/secrets.rs b/app/src/terminal/model/secrets.rs index 594749d485b..241a96c70f2 100644 --- a/app/src/terminal/model/secrets.rs +++ b/app/src/terminal/model/secrets.rs @@ -17,6 +17,7 @@ use super::grid::grid_handler::GridHandler; use super::grid::{Dimensions as _, RespectDisplayedOutput}; use super::terminal_model::RangeInModel; use crate::ai::blocklist::TextLocation; +use crate::safe_warn; use crate::terminal::model::find::RegexDFAs; use crate::terminal::model::index::Point; @@ -376,7 +377,10 @@ pub fn set_user_and_enterprise_secret_regexes<'a>( let dfas = match RegexDFAs::new_many(&all_secrets, false, true) { Ok(dfas) => dfas, Err(err) => { - log::warn!("Failed to construct new RegexDFA with combined secrets: {err:#}"); + safe_warn!( + safe: ("Failed to construct new RegexDFA with combined secrets"), + full: ("Failed to construct new RegexDFA with combined secrets: {err:#}") + ); return; } }; @@ -390,7 +394,10 @@ pub fn set_user_and_enterprise_secret_regexes<'a>( }, }, Err(err) => { - log::warn!("Failed to construct new Regex with combined secrets: {err:#}"); + safe_warn!( + safe: ("Failed to construct new Regex with combined secrets"), + full: ("Failed to construct new Regex with combined secrets: {err:#}") + ); return; } }; diff --git a/app/src/terminal/model/terminal_model.rs b/app/src/terminal/model/terminal_model.rs index bfd340d2b0d..1ffccd7f2a7 100644 --- a/app/src/terminal/model/terminal_model.rs +++ b/app/src/terminal/model/terminal_model.rs @@ -52,6 +52,7 @@ use super::session::{BootstrapSessionType, InBandCommandOutputReceiver, SessionI use super::{Secret, SecretHandle}; use crate::ai::ambient_agents::AmbientAgentTaskId; use crate::ai::blocklist::SerializedBlockListItem; +use crate::safe_warn; use crate::terminal::available_shells::AvailableShell; use crate::terminal::block_filter::BlockFilterQuery; use crate::terminal::block_list_element::GridType; @@ -3162,9 +3163,9 @@ impl ansi::Handler for TerminalModel { uname: data.uname, })) } - None => log::warn!( - "Received invalid shell name in init_subshell: {}", - data.shell + None => safe_warn!( + safe: ("Received invalid shell name in init_subshell"), + full: ("Received invalid shell name in init_subshell: {}", data.shell) ), } } @@ -3186,9 +3187,12 @@ impl ansi::Handler for TerminalModel { )) } None => { - log::warn!( - "Received invalid shell name in SourcedRCFileForWarpValue: {}", - data.shell + safe_warn!( + safe: ("Received invalid shell name in SourcedRCFileForWarpValue"), + full: ( + "Received invalid shell name in SourcedRCFileForWarpValue: {}", + data.shell + ) ); } }