# Exit codes and errors

> What each census exit code means, every error code it can report, and what to do about each one.

## Exit codes

| Code | Status | Meaning |
| --- | --- | --- |
| `0` | `ok`, `complete` | Done. A query succeeded, a scan completed, or a cleanup deleted everything it could. Skipped items are normal. |
| `1` | `failed` | A bad request: arguments, a selection, a missing confirmation. Nothing was deleted. |
| `2` | `failed` | An operational failure: a scan failed, another cleanup was running, the Trash couldn't be read. |
| `4` | `partial` | Partly done: some folders couldn't be read, some items couldn't be fully deleted, or a maintenance task failed. |
| `7` | `not_found` | No saved result: no scan, no review set, or the path or app isn't in the scan. |
| `130` | `cancelled` | Ctrl-C or `SIGTERM` stopped it. |
| `141` | — | stdout closed early (`SIGPIPE`), as in `census top \| head -1`. Nothing is printed. |

With `--json`, the same number is in the envelope's `exit_code`, and `errors` says why.

## Handle errors in a script

```sh
census clean --safe --json > result.json
case $? in
  0) jq -r '"Freed \(.results.freed_bytes) bytes"' result.json ;;
  4) jq -r '.results.items[] | select(.outcome.result == "failed" or .outcome.result == "partial") | .path.display' result.json ;;
  7) echo "No saved scan. Run: census scan" >&2 ;;
  *) jq -r '.errors[0].message' result.json >&2 ;;
esac
```

## Error codes

Every failure has a code in `errors[].code` and a message meant for people.

| Code | Exit | What happened | What to do |
| --- | --- | --- | --- |
| `invalid_request` | 1 | A misspelled command or option, a bad value, or an option given twice. For example `unknown command: tpo (did you mean top?)`. | Fix the arguments. `census help COMMAND` lists a command's options. |
| `ambiguous_app` | 1 | The app name matches more than one app. | Use the app's bundle ID. |
| `output_exists` | 1 | `export --output` names a file that exists. | Pick another path, or add `--force`. |
| `confirmation_required` | 1 | A command that deletes ran without a terminal and without `--safe` or `--yes`. | Pass the flag once the person has agreed. |
| `invalid_selection` | 1 | A path in the selection file, or a `PATH` argument, isn't one census listed. Nothing was deleted. | Copy paths exactly from `review --json`, `duplicates --json` or `large --json`. |
| `review_stale` | 1 | The review set, duplicate search or Large Files listing is more than 7 days old. | Run `census review --json` (or the search) again. |
| `run_as_root` | 1 | A cleanup ran with `sudo`. | Run it as yourself. |
| `cache_unreadable` | 2 | The saved scan couldn't be read. | Scan again. |
| `busy` | 2 | In `census serve`, another long job is running. | Wait for it, then send the request again. |
| `scan_failed` | 2 | The scan couldn't run. | Read the message. |
| `output_failed` | 2 | `export` couldn't write the report. | Check the path and its permissions. |
| `selftest_failed` | 2 | A self-test scenario failed. | See [`selftest`](https://diskcensus.com/docs/cli/utilities.md#selftest). |
| `cleanup_running` | 2 | Another cleanup is running. | Wait for it to finish. Don't retry in a loop. |
| `cleanup_failed` | 2 | The cleanup couldn't run. | Read the message. |
| `trash_unreadable` | 2 | A Trash couldn't be read, so nothing was deleted. | Give the app that runs census Full Disk Access. |
| `partial_scan` | 4 | Some folders couldn't be read. | See `read_errors` in the scan's JSON. Full Disk Access often helps. |
| `partial_cleanup` | 4 | Some items couldn't be fully deleted. | Check each item's `outcome`. |
| `maintenance_failed` | 4 | A maintenance task failed. The others still ran. | Check the task's `result` and `detail`. |
| `no_review` | 7 | There is no review set, duplicate search or Large Files listing to apply. | Run `census review --json` first. |
| `no_cache` | 7 | There is no saved scan for the scope. | Run `census scan`. |
| `path_not_scanned` | 7 | The path isn't in the saved scan. | Scan a scope that includes it. |
| `apps_not_scanned` | 7 | The scan doesn't include your apps. | Run `census scan`, the whole drive. |
| `home_not_scanned` | 7 | The scan doesn't include your home folder. | Run `census scan`, the whole drive. |
| `app_not_found` | 7 | No installed app matches the name. | Check the name with `census apps`. |
| `cancelled` | 130 | The command was stopped. | What was deleted so far is in the audit log. |

## Uninstall errors

`census uninstall` adds a few codes of its own:

| Code | Exit | What happened |
| --- | --- | --- |
| `app_running` | 1 | A program inside the app is still running, so nothing was deleted. census never quits apps. Quit it and try again. |
| `needs_admin` | 1 | The app has a folder you can't change, or a locked or SIP-protected entry. |
| `system_app` | 1 | The app is part of macOS. |
| `not_removable` | 1 | The app can't be removed. |
| `app_not_removed` | 4 | The app wasn't fully deleted, so its data was left as it was. `EPERM` usually means macOS's App Management protection: allow the app that runs census in System Settings › Privacy & Security. |

## Scan read errors

A scan's `read_errors` describes paths it couldn't read. It is scan data, separate from `errors`. Each recorded path has a `code`:

| Code | Meaning | Makes the scan partial |
| --- | --- | --- |
| `sip_protected` | Protected by System Integrity Protection. | No |
| `root_only` | Owned by root, and its permissions deny you. `sudo` can include it. | No |
| `other_owner_private` | Owned by another user or service account. | No |
| `os_protected` | macOS keeps it from every app, even with Full Disk Access. | No |
| `full_disk_access_required` | Needs Full Disk Access, which this process doesn't have. | Yes |
| `access_denied` | Denied for another reason, including your own folder without read permission. | Yes |
| `path_disappeared` | Removed between listing and reading. | No |
