I’d like my workflow to cope gracefully when something fails instead of just stopping. How do error handling and retries work in 3B? I’m curious how to catch a failure, decide what to do next, and automatically retry something that’s likely just a temporary blip. Pointers to the relevant docs or patterns would help a lot.
Great question, and it’s the right instinct. The workflows that hold up in production are the ones that assume things will occasionally break.
Here’s how I’d think about it in three layers.
First, the temporary blips. A lot of failures are just transient: an API times out, you hit a rate limit, a service hiccups for a second. For those, retries are your friend. The trick is to retry with backoff rather than hammering immediately. Wait a moment, try again, wait a little longer, try again, and cap it after a few attempts. That alone clears up the majority of “it failed but worked fine when I reran it” cases. Where you can, make the operation idempotent so a retry can’t accidentally do the same thing twice.
Second, catching the failure so it doesn’t just halt the flow. The idea is to wrap the risky part (usually an HTTP call or a bit of custom code) so that when it errors, you catch it and turn the failure into data instead of a dead stop. Return something like { "status": "error", "reason": "..." } and let the next step read that and decide what to do. Now failure is just another branch, not the end of the road.
Third, deciding what to do next. Once a failure is data you can inspect, you’ve got options: retry it, fall back to a secondary source, skip that one item but keep processing the rest, or escalate. That last one matters. When something genuinely can’t be recovered, don’t fail silently. Route it somewhere a human will see, like a notification or a ticket, with enough context to act on.
A couple of things worth keeping in mind. Not every error should be retried. A 500 or a timeout, sure. A 400 or a 401 won’t fix itself no matter how many times you try, so don’t waste attempts on those. And in a loop over many items, isolate each one so a single bad record doesn’t take down the whole batch.
For pointers, the most useful things to dig into are the code step docs for the catch-and-return-as-data pattern, and anything on retries and backoff for the automatic side.
One cool thing I add to this is 3B’s autofix feature.
It monitors workflows, identifies the root cause of failures, and proposes verified code or configuration fixes, all in a new branch.
It’s not a replacement for the things mentioned in the reply above bought a nice supplementary element that sits alongside it and enhances it.