{"record":{"id":"4db11394110121ac","repo":"astral-sh/ruff","slug":"failed-to-deserialize-diagnostic-data-err","errorCode":null,"errorMessage":"failed to deserialize diagnostic data: {err}","messagePattern":"failed to deserialize diagnostic data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_server/src/lint.rs","lineNumber":305,"sourceCode":"        document: CheckedDocument::Toml(document),\n    }\n}\n\n/// Converts LSP diagnostics to a list of `DiagnosticFix`es by deserializing associated data on each diagnostic.\npub(crate) fn fixes_for_diagnostics(\n    diagnostics: Vec<lsp_types::Diagnostic>,\n) -> crate::Result<Vec<DiagnosticFix>> {\n    diagnostics\n        .into_iter()\n        .filter(|diagnostic| diagnostic.source.as_deref() == Some(DIAGNOSTIC_NAME))\n        .map(move |mut diagnostic| {\n            let Some(data) = diagnostic.data.take() else {\n                return Ok(None);\n            };\n            let fixed_diagnostic = diagnostic;\n            let associated_data: crate::lint::AssociatedDiagnosticData =\n                serde_json::from_value(data).map_err(|err| {\n                    anyhow::anyhow!(\"failed to deserialize diagnostic data: {err}\")\n                })?;\n            Ok(Some(DiagnosticFix {\n                fixed_diagnostic,\n                code: associated_data.code,\n                title: associated_data.title,\n                noqa_edit: associated_data.noqa_edit,\n                edits: associated_data.edits,\n                is_preferred: associated_data.is_preferred,\n            }))\n        })\n        .filter_map(crate::Result::transpose)\n        .collect()\n}\n\nenum CheckedDocument<'a> {\n    Python {\n        source: SourceKind,\n        index: LineIndex,","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_server/src/lint.rs#L287-L323","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Re-trigger diagnostics (save file / restart server) so data is regenerated by the current Ruff version","Update the Ruff server and client extension together so the AssociatedDiagnosticData schema matches","Check that no client plugin rewrites or filters the `data` field of Ruff diagnostics","If persistent, clear cached workspace state in the editor and restart the LSP server"],"exampleFix":"// before (client rewrote data)\ndiagnostic.data = json!({\"source\": \"other\"});\n// after\n// pass the diagnostic through untouched so `data` keeps code/title/noqa_edit\nsend(diagnostic);","handlingStrategy":"try-catch","validationCode":"// Client-side validation before sending a fix request\ndef ruff_diagnostic_data_is_intact(diag):\n    data = diag.get(\"data\") or {}\n    return (\n        isinstance(data.get(\"code\"), (str, int))\n        and isinstance(data.get(\"title\"), str)\n        and (\"noqa_edit\" not in data or isinstance(data[\"noqa_edit\"], dict))\n    )","typeGuard":null,"tryCatchPattern":"// Client (TypeScript)\ntry {\n  await client.sendRequest('workspace/executeCommand', { command: 'ruff.applyAutofix', arguments: [...] });\n} catch (e) {\n  if (String(e.message).includes('failed to deserialize diagnostic data')) {\n    await restartRuffServer(); // regenerate diagnostics with current schema\n  } else throw e;\n}","preventionTips":["Never mutate or strip the `data` field of Ruff diagnostics in client middleware","Keep the Ruff binary and editor extension versions in sync","Clear cached/published diagnostics after a server restart","Filter diagnostics by `source === 'ruff'` before requesting fixes"],"tags":["rust","lsp","serialization","serde","diagnostics"],"backgroundTag":"diagnostic-data-deserialization-failed","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}