{"record":{"id":"8576129cdc30c400","repo":"microsoft/typescript-go","slug":"expected-null-got-s","errorCode":null,"errorMessage":"expected null, got %s","messagePattern":"expected null, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lsp/lsproto/lsp.go","lineNumber":274,"sourceCode":"\t// (absent, null, or a scalar).\n\tif k := raw.Kind(); k != '{' && k != '[' {\n\t\treturn params, fmt.Errorf(\"%w: params must be an object or array\", ErrorCodeInvalidParams)\n\t}\n\tif err := json.Unmarshal(raw, &params); err != nil {\n\t\treturn params, fmt.Errorf(\"%w: %w\", ErrorCodeInvalidParams, err)\n\t}\n\treturn params, nil\n}\n\ntype Null struct{}\n\nfunc (Null) UnmarshalJSONFrom(dec *json.Decoder) error {\n\tdata, err := dec.ReadValue()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif string(data) != \"null\" {\n\t\treturn fmt.Errorf(\"expected null, got %s\", data)\n\t}\n\treturn nil\n}\n\nfunc (Null) MarshalJSONTo(enc *json.Encoder) error {\n\treturn enc.WriteToken(json.Null)\n}\n\ntype NoParams struct{}\n\nfunc (NoParams) IsZero() bool { return true }\n\ntype clientCapabilitiesKey struct{}\n\nfunc WithClientCapabilities(ctx context.Context, caps *ResolvedClientCapabilities) context.Context {\n\treturn context.WithValue(ctx, clientCapabilitiesKey{}, caps)\n}\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/lsp/lsproto/lsp.go#L256-L292","documentation":"Produced by Null.UnmarshalJSONFrom (lsp.go:266-277): several LSP response types are spec'd as literally null (e.g. the result of shutdown or registerCapability responses). The generated code decodes the result into lsproto.Null, which accepts only the exact JSON token null; any other bytes produce this error. It is the response-side analogue of the strict params validation.","triggerScenarios":"A client replies to client/registerCapability or client/unregisterCapability with {} , an empty result, or a non-null value where the server unmarshals the result into lsproto.Null; a test double returning an empty object instead of null for such requests.","commonSituations":"Client frameworks that coerce null results to {} or omit the result member; JSON-RPC libraries that represent null as an empty map; mocks in tests that return zero values rather than JSON null.","solutions":["Make the client reply with an explicit JSON null result for requests whose spec result is null (register/unregister capability).","If the result member is being omitted entirely, send \"result\": null explicitly.","In mocks, marshal lsproto.Null{} (which encodes as null via MarshalJSONTo) instead of an empty struct."],"exampleFix":"// before: client response\n{\"jsonrpc\":\"2.0\",\"id\":\"ts1\",\"result\":{}}\n// after\n{\"jsonrpc\":\"2.0\",\"id\":\"ts1\",\"result\":null}","handlingStrategy":"validation","validationCode":"// client: reply with JSON null for null-result requests\nvar nullResultMethods = map[string]bool{\n    \"client/registerCapability\": true,\n    \"client/unregisterCapability\": true,\n}\n\nfunc resultFor(method string) any {\n    if nullResultMethods[method] {\n        return nil // marshals to JSON null\n    }\n    return computeResult(method)\n}","typeGuard":"func isNullResultMethod(method string) bool {\n    return method == \"client/registerCapability\" || method == \"client/unregisterCapability\"\n}","tryCatchPattern":null,"preventionTips":["Reply with an explicit null result, never {} or an omitted result, for null-result server requests.","In mocks, marshal lsproto.Null{} for such results.","Check the LSP spec result type before implementing client-side handlers."],"tags":["lsp","jsonrpc","validation","protocol"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}