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
- Build the request from the generated params structs in internal/api (proto.go) instead of hand-writing JSON
- Diff your payload field-by-field against the params struct for that exact method in proto.go
- 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
- Generate request payloads from the proto.go structs rather than hand-writing JSON
- Pin client and server to the same typescript-go version so param structs cannot drift
- Add a contract test that round-trips every request you send through UnmarshalJSONFrom
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
- Found ${unusedBaselines.length} unused baseline file(s). Run
- Failed to extract version from version.go
- Cannot run a temporary file update on an inactive snapshot
- Snapshot is disposed
- Cannot create directory: a file already exists at "/${segmen
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/fda5ebe251b6cfa3.
Report an issue: GitHub.