> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and error codes

> Look up a Result error code, an SDK exception class, or a qodercli exit code, and decide how to handle it.

This page is the reference for error **identity**: given a code, an exception class, or an exit code, what it means and how to handle it. If you have a symptom rather than a code — a hang at startup, a tool the agent ignores, a setting that appears to have no effect — start from [Troubleshooting](/cli/sdk/troubleshooting), which is indexed by observed behavior.

Qoder Agent SDK reports task failures, SDK failures, and process exits separately. Handle the most specific signal available instead of treating every non-success condition as an exception.

```text
What failed?
   |
   +-- Agent completed the task unsuccessfully
   |      `result` message: subtype, errors, optional error_code
   |
   +-- SDK could not start or maintain the session
   |      thrown exception: class, code, and diagnostic fields
   |
   `-- qodercli process stopped
          process exit code: transport-level diagnostic
```

The `error_code` in a Result message and the qodercli process exit code are different namespaces. Do not compare one with values from the other.

## Recommended handling order

1. Consume messages until the SDK produces a `result` or raises an exception.
2. For a Result, check `subtype` and `is_error` first. Use `error_code` only to choose a more specific recovery path when it is present.
3. Catch SDK exceptions around the entire iteration. Use the exception type and fields to diagnose configuration, runtime, or transport failures.
4. Log the session ID, Result subtype, error code, and exception name. Do not log authentication values or full source content by default.

An unsuccessful Result and a later process exception can describe the same failed session. Record both for diagnostics, but avoid showing the user two notifications for one failure.

## Result subtypes

| `subtype`                | Meaning                                                                                               | Recommended action                                                                             |
| ------------------------ | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `success`                | The Agent completed the turn                                                                          | Read `result` and continue or close the session                                                |
| `error_during_execution` | The turn stopped because of an execution, model, service, authentication, or unrecoverable tool error | Read `errors`; use `error_code` when available; retry only when the cause is transient         |
| `error_max_turns`        | The Agent reached its configured turn limit                                                           | Inspect for loops or blocked tools, then increase the limit only if more turns are appropriate |

Future runtimes can add Result subtypes. Always keep a fallback branch that records the subtype and `errors` instead of assuming this table is exhaustive.

## Handle Results

TypeScript exposes an optional `number | string` `error_code` on `SDKResultMessage`; Python exposes an optional numeric code on `ResultMessage`. TypeScript preserves CLI string codes such as `storage_insufficient` and unknown codes unchanged. Use the field when it is present, and do not extract a code by parsing human-readable error text.

<CodeGroup>
  ```typescript TypeScript
  import {
    QoderCliProcessError,
    accessTokenFromEnv,
    query,
  } from '@qoder-ai/qoder-agent-sdk';

  let resultReceived = false;

  try {
    for await (const message of query({
      prompt: 'Run the test suite and explain any failures.',
      options: { auth: accessTokenFromEnv() },
    })) {
      if (message.type !== 'result') continue;

      resultReceived = true;
      if (message.subtype === 'success' && !message.is_error) {
        console.log(message.result);
        continue;
      }

      console.error({
        subtype: message.subtype,
        errorCode: message.error_code,
        errors: 'errors' in message ? message.errors : [message.result],
        sessionId: message.session_id,
      });

      if (message.error_code === 105) {
        // Obtain a new credential and create a new SDK session.
      } else if (
        typeof message.error_code === 'number' &&
        [500, 10408, 10500].includes(message.error_code)
      ) {
        // Retry later with bounded exponential backoff.
      }
    }
  } catch (error) {
    if (error instanceof QoderCliProcessError) {
      console.error({
        exitCode: error.exitCode,
        signal: error.signal,
        stderr: error.stderr,
        resultReceived,
      });
    } else {
      throw error;
    }
  }
  ```

  ```python Python
  import anyio

  from qoder_agent_sdk import (
      ProcessError,
      QoderAgentOptions,
      QoderSDKError,
      ResultMessage,
      access_token_from_env,
      query,
  )

  async def main() -> None:
      options = QoderAgentOptions(auth=access_token_from_env())
      result_received = False

      try:
          async for message in query(
              prompt="Run the test suite and explain any failures.",
              options=options,
          ):
              if not isinstance(message, ResultMessage):
                  continue

              result_received = True
              if message.subtype == "success" and not message.is_error:
                  print(message.result)
                  continue

              print(
                  {
                      "subtype": message.subtype,
                      "error_code": message.error_code,
                      "errors": message.errors,
                      "session_id": message.session_id,
                  }
              )

              if message.error_code == 105:
                  # Obtain a new credential and create a new SDK session.
                  pass
              elif message.error_code in (500, 10408, 10500):
                  # Retry later with bounded exponential backoff.
                  pass
      except ProcessError as error:
          print(
              {
                  "exit_code": error.exit_code,
                  "stderr": error.stderr,
                  "result_received": result_received,
              }
          )
      except QoderSDKError as error:
          print({"sdk_error": type(error).__name__, "code": getattr(error, "code", None)})
          raise

  anyio.run(main)
  ```
</CodeGroup>

## Result error codes

The following numeric codes are normalized by the current qodercli runtime and can appear in `message.error_code` in either SDK. The field is optional. qodercli can also pass through a numeric service code not listed here, so preserve unknown values in logs and fall back to `subtype` plus `errors`.

### Authentication and quota

| Code  | Meaning                                         | Recommended action                                                                               |
| ----: | ----------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `105` | Login or access token expired                   | Obtain a valid credential and create a new session; register the authentication-expired callback |
| `110` | Daily usage limit reached                       | Wait for the usage window to reset or review the account limit                                   |
| `113` | Usage quota exhausted                           | Review quota and plan status; do not immediately retry unchanged                                 |
| `114` | Free-trial account limit reached                | Review account eligibility or upgrade options                                                    |
| `115` | Free-user quota reached                         | Wait for quota renewal or review upgrade options                                                 |
| `116` | Team administrator Credits exhausted            | Ask the team administrator to replenish or adjust Credits                                        |
| `117` | Team member Credits exhausted                   | Ask the team administrator to assign or replenish Credits                                        |
| `118` | Personal Credits exhausted                      | Replenish Credits or use an account with available capacity                                      |
| `119` | Free usage limit for the selected model reached | Select an available model, wait for renewal, or review the plan                                  |
| `122` | Billing-group Credits limit reached             | Ask the billing administrator to review the group limit                                          |

### Request and policy

| Code    | Meaning                                                       | Recommended action                                                             |
| ------: | ------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `406`   | Request blocked because of sensitive content or model refusal | Change the request or input content; do not retry it unchanged                 |
| `416`   | Requested range or request shape is not satisfiable           | Inspect `errors`, then reduce or correct the requested range                   |
| `430`   | Requested capability is not supported                         | Upgrade to compatible SDK/qodercli versions or use a supported capability      |
| `47902` | Maximum Agent turns reached                                   | Inspect loops, permissions, and tool failures before increasing the turn limit |
| `48716` | A Hook blocked Agent execution                                | Inspect the relevant Hook decision and update the Hook or task                 |
| `80411` | Input content is too long                                     | Reduce the prompt, attachments, or retained context                            |
| `80412` | Too many images or documents                                  | Reduce the number of media attachments and retry                               |

### Service and model runtime

| Code    | Meaning                      | Recommended action                                                               |
| ------: | ---------------------------- | -------------------------------------------------------------------------------- |
| `500`   | Request or network failure   | Check connectivity and retry with bounded exponential backoff                    |
| `10408` | Request timed out            | Retry with bounded backoff; reduce task scope if timeouts repeat                 |
| `10500` | Model service internal error | Retry later; retain the session ID when contacting support                       |
| `10605` | Model request is queued      | qodercli normally waits and retries; if the code reaches the Result, retry later |

<Warning>Retry only errors known to be transient. Use a maximum attempt count, exponential backoff, and jitter. Authentication, quota, policy, input, and configuration errors require a change before retrying.</Warning>

## SDK exceptions

SDK exceptions mean the application could not configure, start, control, or continue the session. They are separate from an unsuccessful Agent Result.

| Situation                                             | TypeScript                               | Python                                    | Useful fields                                           |
| ----------------------------------------------------- | ---------------------------------------- | ----------------------------------------- | ------------------------------------------------------- |
| Authentication not configured                         | Error with `code: "auth_not_configured"` | Error with `code: "auth_not_configured"`  | `code`                                                  |
| PAT environment variable missing                      | `AuthAccessTokenEnvVarError`             | `AuthAccessTokenEnvVarError`              | `code`                                                  |
| Service Account environment variable missing          | `AuthServiceAccountEnvVarError`          | `AuthServiceAccountEnvVarError`           | `code`                                                  |
| qodercli not found or cannot start                    | `QoderCliProcessError`                   | `CLINotFoundError` / `CLIConnectionError` | message; TypeScript `stderr`; Python path/message       |
| qodercli exits unexpectedly                           | `QoderCliProcessError`                   | `ProcessError`                            | `exitCode` / `exit_code`, `stderr`; TypeScript `signal` |
| Model selection callback times out                    | `ModelPolicyTimeoutError`                | `ModelPolicyTimeoutError`                 | `timeoutMs` / `timeout_ms`                              |
| Protocol version is incompatible                      | `ProtocolVersionMismatchError`           | `ProtocolVersionMismatchError`            | CLI and SDK protocol versions                           |
| Runtime lacks a required capability                   | `UnsupportedCliCapabilityError`          | `UnsupportedCliCapabilityError`           | `capability`                                            |
| CLI returns a failure before initialization completes | `QoderCliInitializationError`            | —                                         | `message`, `code`, `result`                             |

In TypeScript, `startup()` and `query.initializationResult()` throw `QoderCliInitializationError` when the CLI returns a failure Result before initialization completes. Its `message` preserves the CLI error text, `code` preserves the optional numeric or string `error_code`, and `result` contains the original Result. Cancellation remains `AbortError`. Failures after initialization continue to arrive as Result messages.

Machine-readable authentication configuration codes shared by the SDKs are:

| `code`                                        | Meaning                                                       |
| --------------------------------------------- | ------------------------------------------------------------- |
| `auth_not_configured`                         | No authentication method was provided                         |
| `auth_access_token_env_var_not_configured`    | The configured PAT environment variable is absent             |
| `auth_service_account_env_var_not_configured` | The configured Service Account environment variable is absent |

For expired credentials reported after startup, use `onAuthExpired` / `on_auth_expired` and create a new session with a valid credential. See [SDK Authentication](/cli/sdk/authentication).

<div id="qodercli-exit-codes" />

## qodercli process exit codes

Applications using the SDK should normally handle Results and SDK exceptions instead of branching directly on process exit codes. Exit codes are most useful for transport diagnostics or when qodercli is started outside the SDK.

| Exit code | Meaning                                                                                           |
| --------: | ------------------------------------------------------------------------------------------------- |
| `0`       | Process exited normally                                                                           |
| `1`       | General or unclassified failure                                                                   |
| `41`      | Authentication failure; the SDK also triggers the authentication-expired callback when configured |
| `42`      | Invalid input or command-line arguments                                                           |
| `44`      | Fatal sandbox error                                                                               |
| `52`      | Fatal configuration error                                                                         |
| `53`      | Fatal turn-limit error                                                                            |
| `54`      | Fatal tool-execution error                                                                        |
| `130`     | Cancellation or interrupt                                                                         |

Other exit codes or termination signals can come from the operating system, a custom runtime, or a child process. TypeScript exposes them through `QoderCliProcessError.exitCode` and `.signal`; Python exposes an available code through `ProcessError.exit_code`.

## Logging and support

For an actionable failure record, retain:

- SDK language and version
- qodercli version from the `system/init` message, when available
- `session_id`, Result `subtype`, optional `error_code`, and `errors`
- Exception class, machine-readable `code`, process exit code, and signal
- Whether the failure happened before initialization, during a tool call, or after a Result

Redact PATs, Service Account keys, authorization headers, full prompts, source files, and tool output unless they are explicitly required for an approved diagnostic workflow.

## Next steps

- [Troubleshooting](/cli/sdk/troubleshooting) — start from a symptom instead of a code
- [SDK Authentication](/cli/sdk/authentication) — configure credentials and handle expiry
- [Permissions](/cli/sdk/permissions) — understand tool denial and approval behavior
- [Hooks](/cli/sdk/hooks) — diagnose Hook-blocked execution
- [Session Control](/cli/sdk/session-control) — interrupt and manage running sessions
- [SDK References](/cli/sdk/references) — inspect exact TypeScript and Python types
