Skip to content

Routine Error Handling

Garret Premo edited this page Apr 23, 2026 · 1 revision

Routine Error Handling

By default, when a step fails — an HTTP error, a failed assertion, a bad reference — the routine stops immediately. The continueOnError: true flag lets specific steps or loop blocks keep going past failures.

Default behaviour

If any step fails, the routine aborts. Subsequent steps and remaining loop iterations are not executed. The CLI exits with a non-zero status so the failure is visible to CI and scripts.

This is the right default for most workflows — you don't want a teardown to run when setup failed.

continueOnError on a step

Set it on a single step to tolerate that step's failure without stopping the routine:

- name: delete-maybe-missing
  command: pets delete
  args-positional:
    - "999"
  continueOnError: true

- name: this-still-runs
  command: pets list

If delete-maybe-missing returns 404, the routine logs the failure and moves on. The subsequent step runs normally.

Use this for:

  • Best-effort cleanup where missing resources are acceptable
  • Pre-flight checks whose failure is informational, not blocking
  • Pairing with .success to branch on the outcome

continueOnError on a loop block

Put it on a forEach or range block to tolerate failures per iteration — if one iteration fails, the loop moves to the next item instead of aborting:

- name: cleanup-all
  forEach: "$pets_to_delete"
  as: "pet"
  continueOnError: true
  steps:
    - name: delete
      command: pets delete
      args-positional:
        - "$pet.id"

This is the bulk-teardown idiom. Every delete is attempted; some may 404, some may succeed. At the end the routine continues to whatever step follows the loop.

Placement matters. continueOnError on the loop block applies to the whole iteration — if any step in the block fails, the iteration is abandoned and the loop moves on. continueOnError on an individual step inside the block applies only to that step.

Branching on .success

.success is the boolean sibling to continueOnError. Use the two together to build "try, fallback" patterns:

- name: try-primary
  command: auth refresh
  continueOnError: true

- name: fallback-login
  command: auth login
  condition: "$try-primary.success == false"

- name: proceed
  command: pets list

If try-primary succeeds, the fallback is skipped. If it fails, the fallback runs. Either way, proceed happens. See Routine Output Capture → .success for more.

When not to use it

continueOnError makes routines more permissive. That's sometimes what you want — cleanups, best-effort fan-out, smoke tests that should report all failures — but it is a poor fit for:

  • Setup steps. If a fixture fails to create, later steps will reference missing data. Let the routine abort.
  • Authentication. A failed login with continueOnError means every subsequent API call runs unauthenticated.
  • Asserted invariants. If an assert: is guarding a correctness property, silencing it with continueOnError defeats the point.

When in doubt: don't set it. Routines fail loudly by default for a reason.


See also

Clone this wiki locally