# Auto-disable

If a job's runs fail many times in a row (20 by default), cronpad sets the job to `disabled`, stops firing it, and emails the workspace owners. This stops a broken job from sending thousands of requests to an endpoint that's gone, and it keeps the hosted service from being used to flood third parties. Re-enabling the job resets the count.

## How it counts

- The counter `consecutive_failures` goes up by one for each **run** that ends `failed` (after all its retries), not for each attempt.
- Any successful run resets it to zero.
- Skipped and cancelled runs don't change it.

So with `max_attempts: 3` and a threshold of 20, the job is disabled after 20 failed runs (up to 60 attempts).

## Threshold

| Where | Setting | Default |
|---|---|---|
| Per job | `auto_disable_threshold` | Server default |
| Server | `auto_disable.consecutive_failures` | `20` |
| Server | `auto_disable.enabled` | `true` |

On cronpad Cloud, a job's threshold can be lower than the server default but not higher. On self-hosted servers you can raise it per job, or switch the feature off entirely with `auto_disable.enabled = false`.

## When a job is disabled

- `state` becomes `disabled` and `disabled_reason` is set, e.g. `consecutive_failures:20`.
- Queued occurrences are removed; nothing more fires.
- A `job.auto_disabled` event is emitted. It is always emailed to workspace owners (when email is configured), and any [alert rule](../alerts/rules.md) that includes it fires too.
- The audit log records the change with actor `system`.
- The dashboard shows a banner on the job with the last error.

## Re-enabling

Fix the cause, then select **Re-enable** in the dashboard or call:

```sh
curl -X POST "$CRONPAD_URL/api/v1/jobs/$JOB_ID/enable" -H "Authorization: Bearer $CRONPAD_API_KEY"
```

The failure counter resets to zero and the job resumes from its next future occurrence. Occurrences missed while disabled are not replayed.