{"record":{"id":"fcc326d969e500c4","repo":"BoundaryML/baml","slug":"document-controller-not-available-at","errorCode":null,"errorMessage":"Document controller not available at `{}`","messagePattern":"Document controller not available at `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_server/src/session/index.rs","lineNumber":96,"sourceCode":"        // let Some(url) = self.url_for_key(key).cloned() else {\n        //     anyhow::bail!(\"Tried to close unavailable document `{key}`\");\n        // };\n\n        let Some(_) = self.documents.remove(document_key) else {\n            anyhow::bail!(\n                \"tried to close document that didn't exist at {}\",\n                document_key\n            )\n        };\n        Ok(())\n    }\n\n    pub fn document_controller_for_key(\n        &mut self,\n        document_key: &DocumentKey,\n    ) -> anyhow::Result<&mut DocumentController> {\n        let Some(controller) = self.documents.get_mut(document_key) else {\n            anyhow::bail!(\"Document controller not available at `{}`\", document_key);\n        };\n        Ok(controller)\n    }\n\n    // fn url_for_key<'a>(&'a self, key: &'a DocumentKey) -> Option<&'a Url> {\n    //     match key {\n    //         DocumentKey::Text(path) => Some(path),\n    //     }\n    // }\n}\n\n/// A mutable handler to an underlying document.\n/// TODO: Don't use an enum here.\n#[derive(Debug)]\npub enum DocumentController {\n    Text(Arc<TextDocument>),\n}\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_server/src/session/index.rs#L78-L114","documentation":"Raised by Index::document_controller_for_key when looking up a DocumentKey that is not in the documents map. Called by update_text_document, so most users see it as a failure to apply didChange/didOpen updates for a URI the server never registered.","triggerScenarios":"update_text_document (or other controller consumers) invoked with a key absent from the index: missing didOpen, URI case/scheme mismatch, or index cleared by reload.","commonSituations":"Client sends didChange before didOpen; server restarted and lost state while client kept editing; URI normalization differences (e.g. file:// vs untitled:, path casing on Windows).","solutions":["Send textDocument/didOpen before any didChange for the URI","Compare the exact URI string the server registered with the one being sent (scheme, casing, encoding)","If the server was restarted, re-open the document to repopulate the index","Add client-side tracking so changes are only sent for known-open documents"],"exampleFix":"// before\nsendDidChange(uri, changes);\n// after\nif (!serverKnows(uri)) await sendDidOpen(uri, text);\nsendDidChange(uri, changes);","handlingStrategy":"validation","validationCode":"if (!serverKnownDocuments.has(normalizeUri(uri))) await sendDidOpen(uri, text);","typeGuard":"const knows = (uri: string): boolean => serverKnownDocuments.has(uri);","tryCatchPattern":"try { await sendDidChange(uri, changes); } catch (e) { if (String(e).includes('not available')) { await sendDidOpen(uri, currentText); await sendDidChange(uri, changes); } else throw e; }","preventionTips":["Send didOpen before didChange","Normalize URI scheme/case consistently","Reopen documents after server restarts","Log URI mismatches (file:// vs untitled:)"],"tags":["lsp","document","rust"],"backgroundTag":"resource-not-found","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}