{"record":{"id":"bd8bbac7bf87aa37","repo":"warpdotdev/warp","slug":"attempted-to-accept-diff-in-view-only-mode","errorCode":null,"errorMessage":"Attempted to accept diff in view-only mode","messagePattern":"Attempted to accept diff in view-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/src/ai/blocklist/inline_action/code_diff_view.rs","lineNumber":949,"sourceCode":"        self.pending_diffs = pending_diffs;\n        ctx.emit(CodeDiffViewEvent::LoadedDiffs);\n        ctx.notify();\n    }\n\n    pub fn try_accept_action(&mut self, ctx: &mut ViewContext<Self>) {\n        let _ = self.try_accept_action_with_selection(AcceptSelection::Only, ctx);\n    }\n\n    /// Attempts to accept the diff and returns Ok(()) if the accept flow was initiated.\n    /// Returns Err when acceptance is disallowed (e.g. view-only mode).\n    fn try_accept_action_with_selection(\n        &mut self,\n        selection: AcceptSelection,\n        ctx: &mut ViewContext<Self>,\n    ) -> Result<()> {\n        if matches!(self.state, CodeDiffState::ViewOnly { .. }) {\n            report_error!(\"Attempted to accept diff in view-only mode\");\n            return Err(anyhow::anyhow!(\n                \"Attempted to accept diff in view-only mode\"\n            ));\n        }\n\n        match selection {\n            AcceptSelection::Only => {\n                send_telemetry_from_ctx!(\n                    RequestFileEditsTelemetryEvent::EditAcceptClicked(EditAcceptClickedEvent {\n                        identifiers: self.identifiers.clone(),\n                        passive_diff: self.is_passive,\n                    }),\n                    ctx\n                );\n            }\n            AcceptSelection::AndContinueWithAgent => {\n                send_telemetry_from_ctx!(\n                    RequestFileEditsTelemetryEvent::EditAcceptAndContinueClicked(\n                        EditAcceptAndContinueClickedEvent {","sourceCodeStart":931,"sourceCodeEnd":967,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/app/src/ai/blocklist/inline_action/code_diff_view.rs#L931-L967","documentation":"`try_accept_action_with_selection` refuses to accept a diff while `CodeDiffState::ViewOnly` is active (a read-only diff view, e.g. a passive/shared diff). Acceptance is only legal in states that own an actionable edit; the guard also fires `report_error!` to Sentry, because reaching it means the UI let an accept action through that should have been impossible.","triggerScenarios":"An accept command (AcceptSelection::Only or the accept-all path, via keyboard shortcut, button, or action dispatch) executes while the diff view is in ViewOnly state — e.g. a passive diff kept alive after its action completed, or a stale keybinding routed to a read-only diff view.","commonSituations":"Stale keyboard shortcut handling after a view transitions to view-only; accept button not hidden when the state changes; scripted/automation flows invoking accept on a review-only diff.","solutions":["Gate accept affordances (buttons, shortcuts, palette entries) on the diff state before invoking — derive their availability from the same check","Hide or disable the accept control whenever the view enters CodeDiffState::ViewOnly","Unbind or reroute accept commands away from view-only diff views","Treat a Sentry hit from this guard as a caller bug to fix, not noise to silence"],"exampleFix":"// before\nlet _ = self.try_accept_action_with_selection(AcceptSelection::Only, ctx);\n\n// after: skip the attempt entirely in view-only mode\nif !matches!(self.state, CodeDiffState::ViewOnly { .. }) {\n    let _ = self.try_accept_action_with_selection(AcceptSelection::Only, ctx);\n}","handlingStrategy":"type-guard","validationCode":"if matches!(self.state, CodeDiffState::ViewOnly { .. }) {\n    return; // accept is not offered in view-only mode\n}","typeGuard":"fn can_accept_diff(state: &CodeDiffState) -> bool {\n    !matches!(state, CodeDiffState::ViewOnly { .. })\n}","tryCatchPattern":"if let Err(e) = self.try_accept_action_with_selection(selection, ctx) {\n    if e.to_string().contains(\"view-only\") {\n        ctx.notify(); // guarded no-op: keep UI consistent, do not escalate\n    } else {\n        report_error!(e);\n    }\n}","preventionTips":["Derive accept-button visibility and shortcut availability from the same state check used by the guard","Avoid fire-and-forget `let _ =` on fallible UI actions; handle or log the Err","Add UI tests asserting accept is unreachable for view-only diffs (each Sentry hit is a caller bug)"],"tags":["ui","diff","state-machine","guard"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}