microsoft/typescript-go · error · ErrInvalidRequest

%w: %w

Error message

%w: %w

What it means

HandleRequest could not decode the params payload into the struct registered for the method, and the decode error is wrapped in ErrInvalidRequest ("api: invalid request"). Each method in proto.go's unmarshalers map has exactly one params type (e.g. ProfileParams, GetSymbolAtPositionParams); the JSON or msgpack payload must match its field names and types. DocumentIdentifier additionally only accepts a plain string or an object with a uri field.

Source

Thrown at internal/api/session.go:596

}

// HandleRequest implements Handler.
func (s *Session) HandleRequest(ctx context.Context, method string, params json.Value) (any, error) {
	// Handle simple methods that don't need param parsing
	switch method {
	case "echo":
		// Return raw binary for msgpack protocol compatibility
		if s.useBinaryResponses {
			return RawBinary(params), nil
		}
		return params, nil
	case "ping":
		return "pong", nil
	}

	parsed, err := unmarshalPayload(method, params)
	if err != nil {
		return nil, fmt.Errorf("%w: %w", ErrInvalidRequest, err)
	}

	switch method {
	case string(MethodRelease):
		return s.handleRelease(ctx, parsed.(*ReleaseParams))
	case string(MethodInitialize):
		return s.handleInitialize(ctx)
	case string(MethodUpdateSnapshot):
		return s.handleUpdateSnapshot(ctx, parsed.(*UpdateSnapshotParams))
	case string(MethodUpdateTemporarySnapshot):
		return s.handleUpdateTemporarySnapshot(ctx, parsed.(*UpdateTemporarySnapshotParams))
	case string(MethodParseCommandLine):
		return s.handleParseCommandLine(ctx, parsed.(*ParseCommandLineParams))
	case string(MethodReadConfigFile):
		return s.handleReadConfigFile(ctx, parsed.(*ReadConfigFileParams))
	case string(MethodParseJsonConfigFile):
		return s.handleParseJsonConfigFileContent(ctx, parsed.(*ParseJsonConfigFileContentParams))
	case string(MethodParseConfigFile):

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Build the request from the generated params structs in internal/api (proto.go) instead of hand-writing JSON
  2. Diff your payload field-by-field against the params struct for that exact method in proto.go
  3. If client and server come from different typescript-go versions, align them to the same commit/version

Example fix

// before
params := map[string]any{"snapshot": "42", "file": 1337} // wrong types

// after
params := api.GetSymbolAtPositionParams{Snapshot: 42, Project: projID, File: api.DocumentIdentifier{FileName: "/abs/a.ts"}, Position: 10}
Defensive patterns

Strategy: validation

Validate before calling

// Marshal through the real params struct before sending; this proves the shape decodes.
if _, err := json.Marshal(params); err != nil { return err }
// For strict checking, round-trip: marshal then unmarshal into the same struct.
blob, _ := json.Marshal(params)
var probe api.GetSymbolAtPositionParams
if err := json.Unmarshal(blob, &probe); err != nil { return fmt.Errorf("bad payload: %w", err) }

Try / catch

if err != nil {
    if errors.Is(err, api.ErrInvalidRequest) {
        // payload shape mismatch for this method: log method + params and fix the client serializer
    }
    return err
}

Prevention

When it happens

Trigger: Sending snapshot as a string instead of a number; passing a non-string/non-{uri} value for a file field (DocumentIdentifier's unmarshaler rejects other JSON kinds); sending an array instead of an object; a wrong-typed field such as positions: "5"; malformed JSON produced by hand-rolled request building.

Common situations: Version skew between client and server protocol structs after an upgrade; hand-written JSON payloads with typos in field names; msgpack encoders that emit a different shape than the decoder expects; copying a params body from a different method.

Related errors


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