commaai/openpilot · warning · TypeError

-32602

-32602

Error message

params must be a list, object, or omitted

What it means

TypeError (JSON-RPC -32602, invalid params) from rpc._invoke: the 'params' member of a request was present but was neither an object, an array, nor null. Per JSON-RPC 2.0 params must be by-position (array) or by-name (object); anything else cannot be bound to the method signature.

Source

Thrown at openpilot/system/athena/rpc.py:87

  if isinstance(err, str):
    return err
  if isinstance(err, dict):
    data = err.get("data")
    if isinstance(data, dict) and data.get("message"):
      return str(data["message"])
    if err.get("message") is not None:
      return str(err["message"])
  return str(err)


def _invoke(fn: Callable[..., Any], params: Any) -> Any:
  if params is None:
    return fn()
  if isinstance(params, dict):
    return fn(**params)
  if isinstance(params, (list, tuple)):
    return fn(*params)
  raise TypeError("params must be a list, object, or omitted")


def handle(raw: str | bytes | JsonDict, methods: MethodMap | None = None) -> str:
  methods = dispatcher if methods is None else methods

  try:
    msg = raw if isinstance(raw, dict) else loads(raw)
  except (TypeError, ValueError, UnicodeDecodeError):
    return dumps_error(None, "parse error", PARSE_ERROR)

  if not is_call(msg):
    raise ValueError("not a call")

  req_id = msg.get("id")
  name = msg.get("method")
  if not isinstance(name, str):
    return dumps_error(req_id, "invalid request", INVALID_REQUEST)

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Pass positional args as an array: "params": ["carState"]
  2. Pass named args as an object: "params": {"service": "carState"}
  3. Omit params entirely for zero-argument methods; never send a scalar params value

Example fix

// before
{"jsonrpc": "2.0", "method": "getMessage", "params": "carState", "id": 1}

// after
{"jsonrpc": "2.0", "method": "getMessage", "params": {"service": "carState"}, "id": 1}
Defensive patterns

Strategy: type-guard

Validate before calling

def valid_rpc_params(params) -> bool:
    return params is None or isinstance(params, (dict, list))

Type guard

from typing import Any

def is_valid_params(params: Any) -> bool:
    return params is None or isinstance(params, (dict, list, tuple))

Try / catch

try:
    handle(raw, dispatcher)
except TypeError as e:
    if 'params must be a list' in str(e):
        fix_client_payload_shape()  # params was a scalar/string
    raise

Prevention

When it happens

Trigger: Sending params as a bare string, number, or boolean, e.g. {"method":"getMessage","params":"carState"} or params=1000. _invoke checks None/dict/(list,tuple) and raises TypeError otherwise.

Common situations: Clients abbreviating single-argument calls as a bare value instead of a one-element list or an object; generated SDKs typing params loosely; hand-built request dicts.

Related errors


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/91a76d931122b365. Report an issue: GitHub.