{"record":{"id":"30c603a7ff0b849f","repo":"sinelaw/fresh","slug":"active-window-present-async-messages","errorCode":null,"errorMessage":"active window present","messagePattern":"active window present","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/app/async_messages.rs","lineNumber":74,"sourceCode":"    /// This is the single correct way to enumerate buffers for sending a\n    /// per-URI LSP request (pull diagnostics, inlay hints, semantic tokens,\n    /// folding ranges, …) to a language-scoped server. Without the language\n    /// filter, a server configured only for e.g. \"rust\" ends up receiving\n    /// requests for every open URI regardless of type, and a responsible\n    /// server rejects unknown URIs with `file not found (code -32603)` —\n    /// polluting logs and wasting a round-trip per unrelated buffer.\n    ///\n    /// Callers that need richer per-buffer info (line counts, content, file\n    /// paths) can still iterate themselves, but should use the same\n    /// `state.language == language` predicate this helper encodes.\n    pub(crate) fn buffers_for_language(\n        &self,\n        language: &str,\n    ) -> Vec<(BufferId, crate::app::types::LspUri)> {\n        self.windows\n            .get(&self.active_window)\n            .map(|w| &w.buffers)\n            .expect(\"active window present\")\n            .iter()\n            .filter_map(|(buffer_id, state)| {\n                if state.language != language {\n                    return None;\n                }\n                self.active_window()\n                    .buffer_metadata\n                    .get(buffer_id)\n                    .and_then(|m| m.file_uri().cloned())\n                    .map(|uri| (*buffer_id, uri))\n            })\n            .collect()\n    }\n\n    /// Apply diagnostics to a buffer identified by URI.\n    /// Returns `(buffer_id, actually_updated)` if buffer was found, None otherwise.\n    /// `actually_updated` is false when the DIAG CACHE determined no overlay changes were needed.\n    fn apply_diagnostics_to_buffer(","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/app/async_messages.rs#L56-L92","documentation":"Panic from `Option::expect` in `App::buffers_for_language`, a read-only helper listing `(BufferId, LspUri)` pairs for buffers of a given language. It asserts the active window exists whenever LSP work (diagnostics pull, semantic tokens, folding, inlay hints) is requested. `windows.get(&self.active_window)` returning `None` panics instead of returning an empty list.","triggerScenarios":"Any of the callers (`handle_lsp_server_quiescent`, `pull_diagnostics_for_language`, `request_semantic_tokens_for_language`, `request_folding_ranges_for_language`, `request_inlay_hints_for_language`) running when the active window id is missing from `windows` — e.g. LSP quiescence event arriving after the last window closed.","commonSituations":"LSP server becomes ready right as the user closes the window/workspace; app teardown while LSP requests still fire; tests invoking LSP helpers with no window set up.","solutions":["Return `Vec::new()` when the active window is absent — an empty buffer list is the semantically correct answer here.","In callers, skip LSP work when there is no active window (guard before calling buffers_for_language).","Shut down or pause language servers during window/workspace teardown so quiescence events don't arrive windowless.","Keep `active_window` always pointing at a live window while LSP sessions are open."],"exampleFix":"// before\nself.windows\n    .get(&self.active_window)\n    .map(|w| &w.buffers)\n    .expect(\"active window present\")\n    .iter()\n    .filter_map(|(buffer_id, state)| { ... })\n    .collect()\n// after\nself.windows\n    .get(&self.active_window)\n    .map(|w| &w.buffers)\n    .map(|buffers| buffers.iter().filter_map(|(buffer_id, state)| { ... }).collect())\n    .unwrap_or_default()","handlingStrategy":"validation","validationCode":"if app.windows.get(&app.active_window).is_none() {\n    return Vec::new(); // nothing to report for a nonexistent window\n}","typeGuard":"fn active_buffers_ref(app: &App) -> Option<&BufferMap> {\n    app.windows.get(&app.active_window).map(|w| &w.buffers)\n}","tryCatchPattern":"// Default to empty instead of panicking:\napp.windows.get(&app.active_window)\n    .map(|w| &w.buffers)\n    .map(|b| collect_language_buffers(b, language))\n    .unwrap_or_default()","preventionTips":["Return empty collections for windowless states in query helpers.","Pause LSP work when there is no active window.","Shut down language servers before workspace teardown.","Test LSP quiescence events arriving after the last window closes."],"tags":["rust","panic","invariant","lsp","async"],"backgroundTag":"internal-invariant-violation","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}