commaai/openpilot · warning · Exception

not a valid request or response

Error message

not a valid request or response

What it means

Raised in athenad's jsonrpc_handler loop when an incoming websocket message parses as JSON but is neither a call (no 'method' key) nor a response (no 'id' plus 'result'/'error'). Per JSON-RPC 2.0 such a payload is invalid, so the handler raises; the surrounding except pushes a generic error reply back to the cloud.

Source

Thrown at openpilot/system/athena/athenad.py:228

  finally:
    for thread in threads:
      cloudlog.debug(f"athena.joining {thread.name}")
      thread.join()


def jsonrpc_handler(end_event: threading.Event) -> None:
  dispatcher["startLocalProxy"] = partial(startLocalProxy, end_event)
  while not end_event.is_set():
    try:
      data = recv_queue.get(timeout=1)
      msg = loads(data)
      if is_call(msg):
        cloudlog.event("athena.jsonrpc_handler.call_method", data=data)
        send_queue_push(handle(msg, dispatcher), SEND_PRIORITY_HIGH)
      elif is_response(msg):
        log_recv_queue.put_nowait(data)
      else:
        raise Exception("not a valid request or response")
    except queue.Empty:
      pass
    except Exception as e:
      cloudlog.exception("athena jsonrpc handler failed")
      send_queue_push(json.dumps({"error": str(e)}), SEND_PRIORITY_HIGH)


def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = True) -> None:
  item = cur_upload_items[tid]
  if item is not None and item.retry_count < MAX_RETRY_COUNT:
    new_retry_count = item.retry_count + 1 if increase_count else item.retry_count

    item = replace(
      item,
      retry_count=new_retry_count,
      progress=0,
      current=False
    )

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Send proper JSON-RPC 2.0 envelopes: calls need 'method' (+ optional params/id), responses need 'id' plus 'result' or 'error'
  2. If you control the sender, validate messages client-side with the same is_call/is_response logic
  3. Inspect the logged athena.jsonrpc_handler payloads (cloudlog) to find the malformed sender

Example fix

// before
ws.send(json.dumps({"note": "hi"}))

// after
ws.send(json.dumps({"jsonrpc": "2.0", "method": "getMessage", "params": {"service": "carState"}, "id": 1}))
Defensive patterns

Strategy: validation

Validate before calling

from openpilot.system.athena.rpc import is_call, is_response

def valid_envelope(msg: dict) -> bool:
    return is_call(msg) or is_response(msg)

Prevention

When it happens

Trigger: The server/CLI sends a bare JSON array, string, or an object like {"foo": 1} over the athena websocket; loads() succeeds (it is valid JSON, a dict) but is_call and is_response both return False.

Common situations: Hand-crafted test clients not following JSON-RPC 2.0 envelope, a backend bug emitting ack objects without id, or protocol version skew between device and cloud.

Related errors


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