What it catches
What it catches
Every condition is opened once, sends one alert, and stays open until it clears. Clearing sends one recovered message naming what was recovered from. A job failing all night pages you once.
missed
The schedule said a run was due and none started within the grace period. Decided by cw.check(); see Schedules. Closes silently when a run starts.
failed
Any of:
- the function threw (the error’s name, message and the first stack frames are recorded),
- the handler returned a
Responsewith status 400 or above, - the job has an
expectrule and the output did not satisfy it.
Alerts on the first failure by default. Set failuresBeforeAlert: 3 to wait for the third consecutive one, for jobs that flake and self-heal. Consecutive failures are counted either way and shown on the dashboard.
stuck
A run started and never reported finishing within timeout. Marked as timeout by the next check, counted as a failure. Usually a killed process: a serverless limit, a deploy, an OOM.
slow
A successful run took longer than it should. The threshold is:
maxDuration, if the job sets one, or- twice the p95 of the job’s last twenty successful runs, once there are at least five to compare against, with a floor of ten seconds so a job that usually takes 200ms is not called slow at 500ms.
Closes when a successful run is back under the threshold.
over_budget
A metric reported with job.metric(name, value) went above its limit. The limit is:
budget[name], if the job sets one, or- three times the median of that metric over the last twenty successful runs, once there are at least five.
All breaching metrics are listed in one alert. Closes when a run’s metrics are all within limits again.
recovered
A run succeeded and no condition remains open. The message names everything that was open before, for example "after: missed, failed".
expect rules
expect turns a quiet success into a failure when the job produced no evidence of doing its work. The output is whatever the job logged with job.log(), or the string the function returned if it logged nothing.
cw.job("export", { expect: "wrote" }); // output must contain the string
cw.job("export", { expect: /wrote \d+ files/ }); // or match the pattern
cw.job("export", { expect: (out) => out.split("\n").length > 3 }); // or pass a functionBaselines
Baselines use the last twenty successful runs and need at least five. Before that, only explicit limits apply. A job’s history is its own: a slow job is compared to itself.
Silence
cw.silence(name, "2h"), the dashboard button, or the MCP tool. While silenced, nothing new is recorded as an incident and no alerts are sent; conditions that clear during the silence do clear. When the silence ends, the next problem alerts normally.
Output and metrics
Output is capped at 16 KB per run, keeping the tail. Metrics are numbers keyed by name; report as many as you like. Both are stored with the run, shown on the dashboard and in alerts, and handed to the MCP server and to triage.