astral-sh/ruff · error

InternalError

InternalError

Error message

Attempted to add edits for a document that was already edited

What it means

While assembling a WorkspaceEdit, the server accumulates per-document edit sets and guards an invariant: at most one edit set per document URI. If set_edits_for_document is called twice for the same URI in the OptionalVersionedTextDocumentIdentifier-based documentChanges mode, it refuses with this InternalError instead of silently overwriting the earlier edits.

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 d1087a4b9e)

Solutions

  1. Restart the language server / reload the window to clear in-flight edit state
  2. Update to the latest Ruff server — duplicate-edit aggregation bugs get patched
  3. Trigger the operations separately (autofix, then organize imports) instead of combined until fixed
  4. If reproducible, capture tracing logs and file an issue with the command sequence
Defensive patterns

Strategy: validation

Validate before calling

// Server-side (Rust): merge edits per URI instead of adding a second set
use std::collections::BTreeMap;
let mut per_uri: BTreeMap<Uri, Vec<lsp_types::TextEdit>> = BTreeMap::new();
for (uri, edits) in incoming {
    per_uri.entry(uri).or_default().extend(edits);
}
for (uri, edits) in per_uri {
    edit_tracker.set_edits_for_document(uri, version, edits)?; // called once per URI
}

Try / catch

// Rust: a duplicate-edit failure is recoverable — log, keep the first edit set, continue
if let Err(e) = tracker.set_edits_for_document(uri, version, edits) {
    tracing::warn!(%e, %uri, "skipping duplicate edit set");
}

Prevention

When it happens

Trigger: A code path that applies two fix sources (e.g., fix-all plus organize-imports in one command, or a fix touching a notebook and its cell) both producing edits for the same file; duplicate resolve calls for the same document within one edit; regressions in the server's edit aggregation.

Common situations: Bugs in specific Ruff server versions combining commands on the same document; notebook workflows where both notebook-level and cell-level edits target one URI; races between concurrent fix requests on one file.

Related errors


AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20). Data as JSON: /api/errors/29f9e4e8a1f31a61. Report an issue: GitHub.