NousResearch/hermes-agent · error · CodexAppServerError

codex app-server error {code}: {message}

Error message

codex app-server error {code}: {message}

What it means

CodexAppServerError from CodexAppServerClient.request() (agent/transports/codex_app_server.py:236), raised when the JSON-RPC response carries an 'error' object. The exception carries the server's code (default -1 if absent), message, and optional data — it is the codex app-server rejecting the call, not a transport failure.

Source

Thrown at agent/transports/codex_app_server.py:236

    ) -> dict:
        """Send a JSON-RPC request and block on the response. Returns `result`,
        raises CodexAppServerError on `error`."""
        rid = self._take_id()
        q: queue.Queue = queue.Queue(maxsize=1)
        with self._pending_lock:
            self._pending[rid] = _Pending(queue=q, method=method)
        self._send({"id": rid, "method": method, "params": params or {}})
        try:
            msg = q.get(timeout=timeout)
        except queue.Empty:
            with self._pending_lock:
                self._pending.pop(rid, None)
            raise TimeoutError(
                f"codex app-server method {method!r} timed out after {timeout}s"
            )
        if "error" in msg:
            err = msg["error"]
            raise CodexAppServerError(
                code=err.get("code", -1),
                message=err.get("message", ""),
                data=err.get("data"),
            )
        return msg.get("result", {})

    def notify(self, method: str, params: Optional[dict] = None) -> None:
        """Send a JSON-RPC notification (no id, no response expected)."""
        self._send({"method": method, "params": params or {}})

    def respond(self, request_id: Any, result: dict) -> None:
        """Reply to a server-initiated request (e.g. approval prompts)."""
        self._send({"id": request_id, "result": result})

    def respond_error(
        self, request_id: Any, code: int, message: str, data: Optional[Any] = None
    ) -> None:
        """Reply to a server-initiated request with an error."""

View on GitHub (pinned to c896c09c42)

Solutions

  1. Read the exception's .message/.code/.data — they come straight from codex and usually name the offending param.
  2. Match the method/param names against the codex app-server version you spawn; pin or upgrade codex to a tested version.
  3. Handle specific codes differently: -32601 unknown method strongly implies version skew; invalid-params implies a caller bug.
  4. Log the full request params at DEBUG when surfacing this so the failing call is reproducible.

Example fix

# before
result = client.request(method, params)

# after
from agent.transports.codex_app_server import CodexAppServerError
try:
    result = client.request(method, params)
except CodexAppServerError as exc:
    if exc.code == -32601:
        raise RuntimeError(f"codex too old for {method!r}; upgrade codex") from exc
    raise
Defensive patterns

Strategy: try-catch

Try / catch

from agent.transports.codex_app_server import CodexAppServerError

try:
    result = client.request(method, params)
except CodexAppServerError as exc:
    if exc.code == -32601:
        raise UnsupportedCodexVersion(method) from exc
    logger.error("codex rejected %s: %s (%s)", method, exc.message, exc.code)
    raise

Prevention

When it happens

Trigger: Any request whose params the codex server rejects: unknown method name, invalid params shape, invalid model/config values, permission denials, or internal server errors (code -32603) such as the thread/start payload mismatch.

Common situations: Version skew between this client and the installed codex app-server (renamed methods/params); passing a model or cwd the server rejects; malformed params after a refactor of the session layer.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/f892917dbc0cf3ca. Report an issue: GitHub.