{"record":{"id":"31c34ac774762b9d","repo":"astral-sh/ruff","slug":"invalidparams-31c34a","errorCode":"InvalidParams","errorMessage":"JSON parsing failure:\n{json_err}","messagePattern":"JSON parsing failure:\n(.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/ty_server/src/server/api.rs","lineNumber":493,"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`) \\\n                    than the one whose method name was matched against earlier.\"\n                )\n            }\n        })\n        .with_failure_code(server::ErrorCode::InvalidParams)\n}\n\n/// Sends back a response to the client, 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    log_guidance: &str,","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/crates/ty_server/src/server/api.rs#L475-L511","documentation":"Deserializing a request's `params` into the strongly-typed LSP struct failed: request.extract() returned ExtractError::JsonError, so the server answers with InvalidParams and the serde error text (api.rs:493). The method name matched a handler; the payload did not match the schema.","triggerScenarios":"Sending a request whose params have wrong field types or missing required fields — e.g. a Position with string line numbers, or textDocument/hover without a valid TextDocumentIdentifier.","commonSituations":"Hand-rolled LSP clients with sloppy serialization, mismatched protocol-type versions between client library and server, custom fields accidentally replacing spec fields, or JSON numbers overflowing into floats.","solutions":["Compare the sent JSON against the LSP spec types for that exact method","Upgrade the client's lsp-types/protocol library to match the server's spec version","Log the raw outgoing JSON payload and deserialize it locally with the same types to see the field error","Ensure required fields are present and numeric fields are integers"],"exampleFix":"// before\nsendRequest('textDocument/hover', {\n  textDocument: { uri },\n  position: { line: '0', character: 0 },  // string line -> JsonError\n});\n\n// after\nsendRequest('textDocument/hover', {\n  textDocument: { uri },\n  position: { line: 0, character: 0 },\n});","handlingStrategy":"validation","validationCode":"// TS: assert the shape of params against the spec before sending\nfunction assertHoverParams(p: unknown): asserts p is { textDocument: { uri: string }; position: { line: number; character: number } } {\n  const o = p as any;\n  if (typeof o?.textDocument?.uri !== 'string') throw new Error('bad textDocument.uri');\n  if (!Number.isInteger(o?.position?.line) || !Number.isInteger(o?.position?.character))\n    throw new Error('position.line/character must be integers');\n}","typeGuard":"const isValidHoverParams = (p: unknown): p is HoverParams =>\n  typeof (p as any)?.textDocument?.uri === 'string' &&\n  Number.isInteger((p as any)?.position?.line) &&\n  Number.isInteger((p as any)?.position?.character);","tryCatchPattern":"// TS: catch the InvalidParams response and log the serde detail\ntry { await client.sendRequest(method, params); }\ncatch (e: any) {\n  if (e?.code === -32602) { log.error(`bad params for ${method}: ${e.message}`, params); return; }\n  throw e;\n}","preventionTips":["Use a maintained protocol-types library (vscode-languageserver-protocol) instead of hand-built payloads","Keep integers as integers — no stringified numbers from forms/UI","Round-trip test outgoing params through JSON.parse(JSON.stringify(x)) against the types"],"tags":["lsp","json","invalid-params","serialization","request"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}