{"record":{"id":"30923cfe528ad569","repo":"BoundaryML/baml","slug":"only-one-change-event-with-full-text-is-supported-for","errorCode":null,"errorMessage":"Only one change event, with full text, is supported for unsaved files","messagePattern":"Only one change event, with full text, is supported for unsaved files","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_server/src/session.rs","lineNumber":356,"sourceCode":"            session: Arc::new((*self).clone()),\n        })\n    }\n\n    /// Registers a text document at the provided `url`.\n    /// If a document is already open here, it will be overwritten.\n    pub(crate) fn open_text_document(&self, document_key: DocumentKey, document: TextDocument) {\n        self.index.lock().open_text_document(document_key, document);\n    }\n\n    pub(crate) fn set_unsaved_file(\n        &mut self,\n        document_key: &DocumentKey,\n        content_changes: Vec<TextDocumentContentChangeEvent>,\n    ) -> anyhow::Result<()> {\n        let new_contents: String = match content_changes.as_slice() {\n            [event] if event.range.is_none() => event.text.clone(),\n            _ => {\n                anyhow::bail!(\n                    \"Only one change event, with full text, is supported for unsaved files\"\n                )\n            }\n        };\n        for project in self.baml_src_projects.lock().values_mut() {\n            let text_document = TextDocument::new(new_contents.clone(), 0);\n            project\n                .lock()\n                .baml_project\n                .unsaved_files\n                .insert(document_key.clone(), text_document);\n        }\n        Ok(())\n    }\n\n    /// Updates a text document at the associated `key`.\n    ///\n    /// The document key must point to a text document, or this will throw an error.","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_server/src/session.rs#L338-L374","documentation":"set_unsaved_file only supports unsaved (in-memory) documents represented by exactly one content change carrying the full text with no range. Any other shape (multiple incremental changes, ranged edits) is rejected because unsaved buffers are stored as whole-document snapshots.","triggerScenarios":"Client sends didChange for an unsaved/untitled file with multiple TextDocumentContentChangeEvent entries, or a single ranged (incremental) change instead of one full-text change.","commonSituations":"Typing in an untitled VS Code buffer (incremental edits); editor plugins that send incremental diffs for virtual documents; client sync modes (incremental) mismatched with the server's expectation for unsaved files.","solutions":["Send unsaved-file content as a single full-text change event (range omitted)","If your client uses incremental sync, aggregate changes into full text before notifying for untitled files","Save the file so it becomes a regular workspace document handled by the normal path","Update the client integration to force full sync (TextDocumentSyncKind.Full) for unsaved buffers"],"exampleFix":"// before: ranged edit for unsaved doc\nchanges: [{ range: {start:{line:0,character:0},end:{line:0,character:3}}, text: \"foo\" }]\n// after: full-text single event\nchanges: [{ text: fullBufferContents }]","handlingStrategy":"validation","validationCode":"if (isUnsaved(uri) && !(contentChanges.length === 1 && contentChanges[0].range === undefined)) {\n  contentChanges = [{ text: currentBufferText }];\n}","typeGuard":"function isFullTextSync(changes: unknown[]): boolean { return changes.length === 1 && (changes[0] as any).range === undefined; }","tryCatchPattern":"try { await sendUnsavedChange(uri, changes); } catch (e) { if (String(e).includes('full text')) await sendUnsavedChange(uri, [{ text: bufferContents }]); else throw e; }","preventionTips":["Use full-document sync for untitled/unsaved buffers","Set TextDocumentSyncKind.Full for virtual documents","Aggregate incremental edits into full text before notifying","Save untitled files when possible to use the normal path"],"tags":["lsp","unsaved","document-sync","rust"],"backgroundTag":"unsupported-operation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}