astral-sh/ruff · error

failed to deserialize diagnostic data: {err}

Error message

failed to deserialize diagnostic data: {err}

What it means

Ruff's LSP server attaches JSON payload (`data`) to diagnostics it publishes so code actions can map back to the originating lint fix. When a client returns a diagnostic for fix application whose `data` cannot be deserialized into `AssociatedDiagnosticData`, `fixes_for_diagnostics` fails with this anyhow error embedding the serde error.

Source

Thrown at crates/ruff_server/src/lint.rs:305

        document: CheckedDocument::Toml(document),
    }
}

/// Converts LSP diagnostics to a list of `DiagnosticFix`es by deserializing associated data on each diagnostic.
pub(crate) fn fixes_for_diagnostics(
    diagnostics: Vec<lsp_types::Diagnostic>,
) -> crate::Result<Vec<DiagnosticFix>> {
    diagnostics
        .into_iter()
        .filter(|diagnostic| diagnostic.source.as_deref() == Some(DIAGNOSTIC_NAME))
        .map(move |mut diagnostic| {
            let Some(data) = diagnostic.data.take() else {
                return Ok(None);
            };
            let fixed_diagnostic = diagnostic;
            let associated_data: crate::lint::AssociatedDiagnosticData =
                serde_json::from_value(data).map_err(|err| {
                    anyhow::anyhow!("failed to deserialize diagnostic data: {err}")
                })?;
            Ok(Some(DiagnosticFix {
                fixed_diagnostic,
                code: associated_data.code,
                title: associated_data.title,
                noqa_edit: associated_data.noqa_edit,
                edits: associated_data.edits,
                is_preferred: associated_data.is_preferred,
            }))
        })
        .filter_map(crate::Result::transpose)
        .collect()
}

enum CheckedDocument<'a> {
    Python {
        source: SourceKind,
        index: LineIndex,

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Re-trigger diagnostics (save file / restart server) so data is regenerated by the current Ruff version
  2. Update the Ruff server and client extension together so the AssociatedDiagnosticData schema matches
  3. Check that no client plugin rewrites or filters the `data` field of Ruff diagnostics
  4. If persistent, clear cached workspace state in the editor and restart the LSP server

Example fix

// before (client rewrote data)
diagnostic.data = json!({"source": "other"});
// after
// pass the diagnostic through untouched so `data` keeps code/title/noqa_edit
send(diagnostic);
Defensive patterns

Strategy: try-catch

Validate before calling

// Client-side validation before sending a fix request
def ruff_diagnostic_data_is_intact(diag):
    data = diag.get("data") or {}
    return (
        isinstance(data.get("code"), (str, int))
        and isinstance(data.get("title"), str)
        and ("noqa_edit" not in data or isinstance(data["noqa_edit"], dict))
    )

Try / catch

// Client (TypeScript)
try {
  await client.sendRequest('workspace/executeCommand', { command: 'ruff.applyAutofix', arguments: [...] });
} catch (e) {
  if (String(e.message).includes('failed to deserialize diagnostic data')) {
    await restartRuffServer(); // regenerate diagnostics with current schema
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a fix code action (e.g. `ruff.applyAutofix` via fixes_for_diagnostics) where a diagnostic's `data` field is missing expected keys (`code`, `title`, `noqa_edit`) or has wrong types — typically because the client modified, cached, filtered, or round-tripped the diagnostic through another server/tool.

Common situations: Editor extensions that copy or transform diagnostics between servers; stale diagnostics from an older Ruff version after upgrade whose data schema changed; clients that serialize/deserialize data lossy (dropping nested objects).

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/4db11394110121ac. Report an issue: GitHub.