microsoft/typescript-go · error

expected null, got %s

Error message

expected null, got %s

What it means

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.

Source

Thrown at internal/lsp/lsproto/lsp.go:274

	// (absent, null, or a scalar).
	if k := raw.Kind(); k != '{' && k != '[' {
		return params, fmt.Errorf("%w: params must be an object or array", ErrorCodeInvalidParams)
	}
	if err := json.Unmarshal(raw, &params); err != nil {
		return params, fmt.Errorf("%w: %w", ErrorCodeInvalidParams, err)
	}
	return params, nil
}

type Null struct{}

func (Null) UnmarshalJSONFrom(dec *json.Decoder) error {
	data, err := dec.ReadValue()
	if err != nil {
		return err
	}
	if string(data) != "null" {
		return fmt.Errorf("expected null, got %s", data)
	}
	return nil
}

func (Null) MarshalJSONTo(enc *json.Encoder) error {
	return enc.WriteToken(json.Null)
}

type NoParams struct{}

func (NoParams) IsZero() bool { return true }

type clientCapabilitiesKey struct{}

func WithClientCapabilities(ctx context.Context, caps *ResolvedClientCapabilities) context.Context {
	return context.WithValue(ctx, clientCapabilitiesKey{}, caps)
}

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Make the client reply with an explicit JSON null result for requests whose spec result is null (register/unregister capability).
  2. If the result member is being omitted entirely, send "result": null explicitly.
  3. In mocks, marshal lsproto.Null{} (which encodes as null via MarshalJSONTo) instead of an empty struct.

Example fix

// before: client response
{"jsonrpc":"2.0","id":"ts1","result":{}}
// after
{"jsonrpc":"2.0","id":"ts1","result":null}
Defensive patterns

Strategy: validation

Validate before calling

// client: reply with JSON null for null-result requests
var nullResultMethods = map[string]bool{
    "client/registerCapability": true,
    "client/unregisterCapability": true,
}

func resultFor(method string) any {
    if nullResultMethods[method] {
        return nil // marshals to JSON null
    }
    return computeResult(method)
}

Type guard

func isNullResultMethod(method string) bool {
    return method == "client/registerCapability" || method == "client/unregisterCapability"
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/8576129cdc30c400. Report an issue: GitHub.