# witr Exit Codes Reference: How to Handle Errors in Shell Scripts

> Learn witr exit codes 0-4 to handle shell script errors effectively. Understand success, usage, config, and runtime failures for robust automation.

- Repository: [Pranshu Parmar/witr](https://github.com/pranshuparmar/witr)
- Tags: api-reference
- Published: 2026-08-10

---

**witr uses five specific exit codes (0, 1, 2, 3, 4) that let automation scripts distinguish between success, usage mistakes, configuration problems, and runtime failures.**

When building automation around the `witr` container management tool, understanding its exit code behavior is essential for reliable CI/CD pipelines and shell scripts. The `pranshuparmar/witr` repository implements a clear, predictable exit code system defined in [`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go) and applied consistently through [`internal/app/app.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/app.go).

## Complete List of witr Exit Codes

The following table covers every exit code used by witr as implemented in the source code:

| Exit code | Meaning | When returned |
|-----------|---------|-------------|
| **0** | Success | Command completed without errors |
| **1** | Generic error | Unexpected internal problem (panic, I/O failure) |
| **2** | Invalid arguments | Malformed flags, unknown sub-commands, or CLI contract violation |
| **3** | Configuration error | Missing or invalid [`witr.yaml`](https://github.com/pranshuparmar/witr/blob/main/witr.yaml) file |
| **4** | Runtime/dependency error | Docker, Podman, or other required tools unavailable or failing |

These constants are defined in [`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go) and invoked via `os.Exit(ece.code)` in [`internal/app/app.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/app.go).

## How to Check witr Exit Codes in Scripts

### Basic Success/Failure Detection

The simplest pattern checks `$?` immediately after witr invocation:

```bash
witr status
if [ $? -eq 0 ]; then
    echo "All containers are healthy"
else
    echo "witr reported an issue"
fi

```

### Granular Error Handling with case Statements

For robust automation, use a `case` statement to handle specific witr exit codes differently:

```bash
witr up
case $? in
    0)  echo "Containers started successfully";;
    2)  echo "Invalid flags – check your command line"; exit 1;;
    4)  echo "Docker/Podman not reachable – retry later"; exit 1;;
    *)  echo "Unexpected error (code $?) – aborting"; exit 1;;
esac

```

### CI Pipeline Retry Logic for Transient Failures

Exit code 4 (runtime error) often indicates temporary conditions worth retrying:

```bash
attempt=0
max=3
while [ $attempt -lt $max ]; do
    witr up && break
    rc=$?
    if [ $rc -eq 4 ]; then
        echo "Runtime unavailable, retry #$((attempt+1))"
        attempt=$((attempt+1))
        sleep 5
    else
        echo "Fatal error (code $rc) – aborting"
        exit $rc
    fi
done

```

## Source Code Locations for witr Exit Codes

Understanding where these codes originate helps with debugging and contributions:

- **[`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go)** — Declares numeric constants for each exit condition
- **[`internal/app/app.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/app.go)** — Central entry point that maps errors to exit codes via `os.Exit(ece.code)`
- **[`cmd/witr/main.go`](https://github.com/pranshuparmar/witr/blob/main/cmd/witr/main.go)** — CLI bootstrap that propagates the final exit status
- **[`README.md`](https://github.com/pranshuparmar/witr/blob/main/README.md)** — Documents basic success (`0`) and error (`1`) outcomes for end-users

## Mapping Exit Codes to Script Actions

| Scenario | Recommended handling |
|----------|-------------------|
| CI/CD success gate | Assert ` $? -eq 0 ` before proceeding |
| User input validation | Treat code **2** as hard failure (don't retry) |
| Missing config file | Treat code **3** as setup error requiring human intervention |
| Container runtime offline | Retry loop on code **4** with exponential backoff |
| Unknown failures | Log and alert on any unhandled code |

## Summary

- **witr defines five exit codes** (0 through 4) in [`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go)
- **Code 2** signals usage errors that require fixing the command invocation
- **Code 3** indicates [`witr.yaml`](https://github.com/pranshuparmar/witr/blob/main/witr.yaml) configuration problems
- **Code 4** enables retry logic for transient runtime/dependency failures
- **Always check `$?` immediately** after witr commands in scripts, as subsequent commands overwrite the value

## Frequently Asked Questions

### What exit code does witr return on success?

witr returns **0** on successful completion. This is implemented consistently across all commands and documented in the [`README.md`](https://github.com/pranshuparmar/witr/blob/main/README.md).

### How can I detect if witr failed due to bad command-line arguments?

Check for **exit code 2**. This specifically indicates invalid arguments or usage errors, as defined in [`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go) and applied in [`internal/app/app.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/app.go).

### Should my script retry when witr exits with code 4?

Yes, **exit code 4** typically indicates transient runtime or dependency failures (e.g., Docker daemon not yet ready). This is the appropriate candidate for retry logic, unlike code 2 (usage) or code 3 (configuration) which require human intervention.

### Where are witr's exit codes defined in the source code?

The numeric constants live in **[`internal/app/exitcode.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/exitcode.go)**, while the actual `os.Exit()` calls that terminate the process with these codes occur in **[`internal/app/app.go`](https://github.com/pranshuparmar/witr/blob/main/internal/app/app.go)**.