{"record":{"id":"83d6385c49c59708","repo":"microsoft/typescript-go","slug":"32602-83d638","errorCode":"-32602","errorMessage":"%w: %w","messagePattern":"%w: %w","errorType":"error_code","errorClass":"ErrorCode","httpStatus":null,"severity":"error","filePath":"internal/lsp/server.go","lineNumber":135,"sourceCode":"\terr error\n}\n\nfunc (e *messageMarshalError) Error() string { return \"failed to marshal message: \" + e.err.Error() }\n\nfunc (e *messageMarshalError) Unwrap() []error {\n\treturn []error{lsproto.ErrorCodeInternalError, e.err}\n}\n\nfunc (r *lspReader) Read() (*lsproto.Message, error) {\n\tdata, err := r.r.Read()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treq := &lsproto.Message{}\n\tif err := json.Unmarshal(data, req); err != nil {\n\t\tif errors.Is(err, lsproto.ErrorCodeInvalidParams) {\n\t\t\treturn req, fmt.Errorf(\"%w: %w\", lsproto.ErrorCodeInvalidParams, err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%w: %w\", lsproto.ErrorCodeInvalidRequest, err)\n\t}\n\n\treturn req, nil\n}\n\nfunc ToReader(r io.Reader) Reader {\n\treturn &lspReader{r: lsproto.NewBaseReader(r)}\n}\n\nfunc (w *lspWriter) Write(msg *lsproto.Message) error {\n\tdata, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn &messageMarshalError{err: err}\n\t}\n\treturn w.w.Write(data)\n}","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/lsp/server.go#L117-L153","documentation":"In lspReader.Read (server.go:126-141), an inbound message failed JSON decoding with an error that errors.Is-matches ErrorCodeInvalidParams — i.e. UnmarshalParams already rejected the payload (NoParams violation, non-object params, bad nested fields). The reader re-wraps it as ErrorCodeInvalidParams (-32602) and, notably, still returns the partially populated *lsproto.Message so the dispatcher can send a per-request error response instead of killing the connection.","triggerScenarios":"Any inbound request carrying malformed params per UnmarshalParams: params on a NoParams method, scalar/null params, or object params failing nested validation — the error surfaces here when Message.UnmarshalJSON eagerly decodes params for known methods.","commonSituations":"Malformed client requests in production logs; debugging why a particular request got a -32602 response; test harnesses asserting the server responds Invalid params rather than Invalid request for shape-valid JSON with bad params.","solutions":["Inspect the wrapped cause after '-32602:' — it is one of the UnmarshalParams errors (expected no params / must be an object or array / nested field detail); fix the client payload accordingly.","Keep the connection alive: this error path is recoverable per-request; ensure middleware does not treat it as fatal or close the stream.","When testing, use errors.Is(err, lsproto.ErrorCodeInvalidParams) to assert the classification rather than parsing message text."],"exampleFix":"// asserting classification in a Go test\n// before\nif err == nil { t.Fatal(\"expected error\") }\n// after\nif !errors.Is(err, lsproto.ErrorCodeInvalidParams) { t.Fatalf(\"want InvalidParams, got %v\", err) }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isInvalidParams(err error) bool {\n    return errors.Is(err, lsproto.ErrorCodeInvalidParams)\n}","tryCatchPattern":"msg, err := reader.Read()\nif err != nil {\n    if errors.Is(err, lsproto.ErrorCodeInvalidParams) {\n        // msg is non-nil: respond per-request with -32602 and keep the connection\n        sendError(msg.Request != nil && msg.Request.ID != nil, err)\n        continue\n    }\n    return err // transport-level failure; stop\n}","preventionTips":["Keep reading after -32602 errors; the connection stays valid and the partially decoded message is returned for error responses.","Classify with errors.Is against lsproto.ErrorCodeInvalidParams.","Log the joined cause to identify which UnmarshalParams rule rejected the payload."],"tags":["lsp","jsonrpc","error-wrapping","validation"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}