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

# Exit Codes

> DevHelm CLI exit codes — success, error categories, and CI-friendly drift detection

The CLI uses specific exit codes so you can branch on outcome in scripts and CI pipelines without parsing stdout.

## Exit code reference

| Code | Name | When it's used |
| - | - | - |
| `0` | Success | Command completed successfully |
| `1` | General error | Unexpected internal failure (uncaught exception, bug) |
| `2` | Usage error | Command-line parse failure from the CLI framework: unknown command, nonexistent flag, missing required argument or flag, invalid enum value |
| `4` | Validation | Local precondition failed: missing/invalid token, malformed YAML, request body that doesn't match the schema |
| `10` | Changes pending | `plan` / `deploy --dry-run --detailed-exitcode` detected pending changes |
| `11` | API error | API returned a non-2xx response (4xx or 5xx). Carries `status`, `code`, and `requestId` in stderr |
| `12` | Transport | Network failure before getting a response: DNS, connection refused, TLS, timeout |
| `13` | Partial failure | `deploy` finished but at least one resource operation failed; the remainder succeeded |

The mapping is implemented in [`src/lib/errors.ts`](https://github.com/devhelmhq/cli/blob/main/src/lib/errors.ts) (`EXIT_CODES`). Sub-classes (e.g. `DevhelmAuthError`, `DevhelmNotFoundError`) inherit their root's exit code. Exit `2` comes from the oclif framework before the command runs, so it is not part of `EXIT_CODES`.

## Quick decision table

| You want to... | Check |
| - | - |
| Detect any failure | `$? -ne 0` |
| Distinguish "config drift" from real errors in CI | `$? -eq 10` for drift, `$? -eq 0` for clean, anything else for failure |
| Retry only on transient failures | Retry on `12`; do **not** retry on `2`, `4`, or `11` (deterministic) |
| Surface auth problems to users | Look for `4` (no token / bad config) or `11` with `code=UNAUTHORIZED` / `code=FORBIDDEN` in stderr (rejected token) |
| Continue past partial deploy failure | Treat `13` as "completed with errors" and inspect the deploy report |

## Usage in CI

### Gate merges on config drift

Use `--detailed-exitcode` with `deploy --dry-run` to detect config changes in a PR check:

```bash theme={null}
devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
```

| Exit code | CI behavior |
| - | - |
| `0` | Config is in sync — pass the check |
| `10` | Config has changes — fail or flag for review |
| `2` / `4` / `11` / `12` | Error — fail the check |

### Shell scripting

```bash theme={null}
devhelm monitors list -o json > monitors.json
case $? in
  0) echo "OK" ;;
  4) echo "Config error — fix and retry"; exit 1 ;;
  11) echo "API error — see request id in stderr"; exit 1 ;;
  12) echo "Network error — will retry"; sleep 5; exec "$0" "$@" ;;
  *) echo "Failed"; exit 1 ;;
esac
```

### GitHub Actions

```yaml theme={null}
- name: Check for drift
  run: devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
  continue-on-error: true
  id: drift

- name: Comment on PR
  if: steps.drift.outcome == 'failure'
  run: echo "Monitoring config has pending changes"
```

## Next steps

<CardGroup cols={2}>
  <Card title="Deploy commands" icon="rocket" href="/cli/commands/deploy">
    Full deploy, plan, and validate reference.
  </Card>

  <Card title="GitHub Actions" icon="github" href="/integrations/github-actions">
    CI/CD integration with the setup-devhelm action.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.