BoundaryML/baml · error
Only one change event, with full text, is supported for unsa
Error message
Only one change event, with full text, is supported for unsaved files
What it means
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.
Source
Thrown at engine/language_server/src/session.rs:356
session: Arc::new((*self).clone()),
})
}
/// Registers a text document at the provided `url`.
/// If a document is already open here, it will be overwritten.
pub(crate) fn open_text_document(&self, document_key: DocumentKey, document: TextDocument) {
self.index.lock().open_text_document(document_key, document);
}
pub(crate) fn set_unsaved_file(
&mut self,
document_key: &DocumentKey,
content_changes: Vec<TextDocumentContentChangeEvent>,
) -> anyhow::Result<()> {
let new_contents: String = match content_changes.as_slice() {
[event] if event.range.is_none() => event.text.clone(),
_ => {
anyhow::bail!(
"Only one change event, with full text, is supported for unsaved files"
)
}
};
for project in self.baml_src_projects.lock().values_mut() {
let text_document = TextDocument::new(new_contents.clone(), 0);
project
.lock()
.baml_project
.unsaved_files
.insert(document_key.clone(), text_document);
}
Ok(())
}
/// Updates a text document at the associated `key`.
///
/// The document key must point to a text document, or this will throw an error.View on GitHub (pinned to bd85ce9dee)
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
Example fix
// before: ranged edit for unsaved doc
changes: [{ range: {start:{line:0,character:0},end:{line:0,character:3}}, text: "foo" }]
// after: full-text single event
changes: [{ text: fullBufferContents }] Defensive patterns
Strategy: validation
Validate before calling
if (isUnsaved(uri) && !(contentChanges.length === 1 && contentChanges[0].range === undefined)) {
contentChanges = [{ text: currentBufferText }];
} Type guard
function isFullTextSync(changes: unknown[]): boolean { return changes.length === 1 && (changes[0] as any).range === undefined; } Try / catch
try { await sendUnsavedChange(uri, changes); } catch (e) { if (String(e).includes('full text')) await sendUnsavedChange(uri, [{ text: bufferContents }]); else throw e; } Prevention
- 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
When it happens
Trigger: Client sends didChange for an unsaved/untitled file with multiple TextDocumentContentChangeEvent entries, or a single ranged (incremental) change instead of one full-text change.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- {0}
- Notification not supported: {0}
- Request not supported: {0}
- Failed to serialize request result: {0}
- no filesystem is attached to this server ({})
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/30923cfe528ad569.
Report an issue: GitHub.