{"record":{"id":"bfae109e0dbeca60","repo":"astral-sh/ruff","slug":"json-parsing-failure-json-err","errorCode":null,"errorMessage":"JSON parsing failure:\n{json_err}","messagePattern":"JSON parsing failure:\n(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_server/src/server/api.rs","lineNumber":308,"sourceCode":"/// Tries to cast a serialized request from the server into\n/// a parameter type for a specific request handler.\n/// It is *highly* recommended to not override this function in your\n/// implementation.\nfn cast_request<Req>(\n    request: server::Request,\n) -> Result<(\n    RequestId,\n    <<Req as RequestHandler>::RequestType as Request>::Params,\n)>\nwhere\n    Req: RequestHandler,\n    <<Req as RequestHandler>::RequestType as Request>::Params: UnwindSafe,\n{\n    request\n        .extract(Req::METHOD.as_str())\n        .map_err(|err| match err {\n            json_err @ server::ExtractError::JsonError { .. } => {\n                anyhow::anyhow!(\"JSON parsing failure:\\n{json_err}\")\n            }\n            server::ExtractError::MethodMismatch(_) => {\n                unreachable!(\n                    \"A method mismatch should not be possible here \\\n                    unless you've used a different handler (`Req`) than the one \\\n                    whose method name was matched against earlier.\"\n                )\n            }\n        })\n        .with_failure_code(server::ErrorCode::InternalError)\n}\n\n/// Sends back a response to the server, but only if the request wasn't cancelled.\nfn respond<Req>(\n    id: &RequestId,\n    result: Result<<<Req as RequestHandler>::RequestType as Request>::Result>,\n    client: &Client,\n) where","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_server/src/server/api.rs#L290-L326","documentation":"`cast_request` extracts and deserializes a request's params into the typed parameters of handler `Req`. If the JSON fails to parse/validate against the expected type (`ExtractError::JsonError`), it is wrapped as `JSON parsing failure:` with the serde detail; a method mismatch is treated as an internal unreachable bug.","triggerScenarios":"A client sends a request whose `params` do not match the LSP schema for that method — wrong field types, missing required fields, nulls where objects are expected — and the server dispatches it to the matched handler.","commonSituations":"Hand-rolled or buggy LSP clients sending malformed JSON-RPC; custom tooling constructing requests manually; client/server version skew where params schema changed; string-vs-number positions or URIs sent as plain strings instead of DocumentUri.","solutions":["Log the raw request params in the client and validate them against the LSP schema for the method","Fix the client's serialization of params (correct types, required fields, DocumentUri formatting)","Update client and server to matching versions to eliminate schema skew","Test the request with an LSP inspector (e.g. vscode-lspInspector) to compare against a working client"],"exampleFix":"// before\n{ \"method\": \"textDocument/formatting\", \"params\": { \"uri\": \"file.py\", \"options\": {} } }\n// after\n{ \"method\": \"textDocument/formatting\",\n  \"params\": { \"textDocument\": { \"uri\": \"file:///abs/file.py\" }, \"options\": { \"tabSize\": 4, \"insertSpaces\": true } } }","handlingStrategy":"try-catch","validationCode":"// Client-side param validation before sendRequest\nfunction validFormatParams(p: any): boolean {\n  return p && typeof p.textDocument?.uri === 'string'\n    && p.textDocument.uri.startsWith('file://')\n    && typeof p.options?.tabSize === 'number'\n    && typeof p.options?.insertSpaces === 'boolean';\n}","typeGuard":null,"tryCatchPattern":"// TypeScript\ntry {\n  return await client.sendRequest('textDocument/formatting', params);\n} catch (e) {\n  if (/JSON parsing failure/.test(String(e.message))) {\n    console.error('Malformed params sent to Ruff:', params); // fix sender\n    return null;\n  }\n  throw e;\n}","preventionTips":["Use a typed LSP client library rather than hand-building JSON-RPC","Validate params against the LSP metaModel/schema for the method","Keep client and server versions matched to avoid schema drift","Always send URIs as absolute file:// DocumentUri strings"],"tags":["rust","lsp","json","serialization","server"],"backgroundTag":"json-params-parse-failure","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}