Runs

Error handling

A failing step fails the run by default. Set retry, continue, or retry then continue per step, wire the error port to a fallback lane, and read failures.

By default a failing step fails the run. That's loud and immediate, which is what you want while building. Production workflows usually want something gentler on the steps that talk to the outside world.

Per-step strategies

Steps that can fail (web request, AI, connected apps) have an On failure setting:

strategy behavior
fail (default) the step and the run fail; the run detail shows where and why
retry re-run the step up to 5 times with a backoff you set; exhausting retries fails the run
continue don't fail; route a {ok: false, error: …} payload out the step's error port
retry_then_continue retry first; if still failing, continue out the error port

The error port pattern

With continue, the step's error port becomes a wired lane:

web request ─ ok    → normal path
            └ error → set fields (context) → send email (alert)

The error payload carries ok: false and the failure reason. Branch on it, log it to a store, or alert someone. The run completes (that's the point), so watch the error lane, not the run status, for these failures.

Reading failures

A failed run shows the failing step in red on its step timeline, with the exact input it received, the error, and an attempt N chip when retries ran. Repair with AI on the failing step opens the canvas with the failure loaded so Max can fix the config and re-verify.

Timeouts and stuck runs

  • Web requests have a per-step timeout (default 30s).
  • A run whose job dies out from under it (deploy, crash) doesn't hang forever. A sweeper marks it failed with an "orphaned" error rather than leaving it running.

Gotchas

  • continue requires wiring the error port. An unwired error lane means failures route into nothing and vanish. The canvas flags this.
  • Retries re-run the whole step, so keep retried steps idempotent (GETs, upserts) and put non-idempotent sends after the shakiest step, not before it.