astral-sh/ruff · error
Attempted to add edits for a document that was already edite
Error message
Attempted to add edits for a document that was already edited
What it means
The LSP server's `DocumentChanges` edit container forbids two `TextDocumentEdit` entries for the same document URI. `set_edits_for_document` scans existing entries and throws this anyhow error if the URI was already added, guarding against duplicate/conflicting edit batches in a single WorkspaceEdit.
Source
Thrown at crates/ruff_server/src/edit.rs:146
Ok(())
}
/// Sets the edits made to a specific document. This should only be called
/// once for each document `uri`, and will fail if this is called for the same `uri`
/// multiple times.
pub(crate) fn set_edits_for_document(
&mut self,
uri: Uri,
_version: DocumentVersion,
edits: Vec<lsp_types::TextEdit>,
) -> crate::Result<()> {
match self {
Self::DocumentChanges(document_edits) => {
if document_edits
.iter()
.any(|document| document.text_document.text_document_identifier.uri == uri)
{
return Err(anyhow::anyhow!(
"Attempted to add edits for a document that was already edited"
));
}
document_edits.push(lsp_types::TextDocumentEdit {
text_document: lsp_types::OptionalVersionedTextDocumentIdentifier {
text_document_identifier: TextDocumentIdentifier { uri },
// TODO(jane): Re-enable versioned edits after investigating whether it could work with notebook cells
version: None,
},
edits: edits.into_iter().map(lsp_types::Edit::TextEdit).collect(),
});
Ok(())
}
Self::Changes(changes) => {
if changes.get(&uri).is_some() {
return Err(anyhow::anyhow!(
"Attempted to add edits for a document that was already edited"
));View on GitHub (pinned to 26f38c119c)
Solutions
- Ensure each document's edits are collected once: merge edit lists before calling set_edits_for_document
- Combine fixes and noqa edits for a document into a single set_edits_for_document call
- Check callers (quick_fix, noqa_comments) so a document with multiple diagnostics funnels through one path
- If duplicate entry is legitimate, convert the flow to use the `Changes` map variant, which keys by URI
Example fix
// before changes.set_edits_for_document(uri, fix_edits)?; changes.set_edits_for_document(uri, noqa_edits)?; // panics: duplicate // after let mut all_edits = fix_edits; all_edits.extend(noqa_edits); changes.set_edits_for_document(uri, all_edits)?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: check membership before inserting
fn can_add(changes: &DocumentChanges, uri: &Url) -> bool {
!changes.iter().any(|d| d.text_document.text_document_identifier.uri == *uri)
}
// call: assert!(can_add(&document_changes, &uri)); Try / catch
// Rust
changes.set_edits_for_document(uri.clone(), edits)
.with_context(|| format("failed to register edits for {uri}"))?; Prevention
- Aggregate all edits for a document (fixes + noqa) before one set_edits_for_document call
- Keep a seen-URIs set in request handlers that loop over multiple diagnostics
- Ensure each handler builds its own fresh WorkspaceEdit per request
- Deduplicate diagnostics by URI before generating fixes
When it happens
Trigger: Calling `set_edits_for_document(uri, ...)` (directly or via `set_fixes_for_document`, `quick_fix`, or `noqa_comments`) twice for the same open document URI within one WorkspaceEdit being built.
Common situations: A code action request that both applies quick fixes and adds noqa edits for the same file; overlapping diagnostics each producing a fix for the same document; custom integrations invoking fix and format paths together.
Related errors
- Invalid command `{name}`
- MethodNotFound
- InternalError
- JSON parsing failure: {json_err}
- `python_extension` is not expected to be combined with the i
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/12748485061be3d1.
Report an issue: GitHub.