Retries
YieldStar implements structured retries through RetryableError. Throwing this error inside a step.run signals to the runtime that the step should be re-executed according to the specified retry policy.
Basic retry
import { RetryableError } from "yieldstar";
yield* step.run(async () => {
const res = await fetch("https://api.example.com/charge");
if (!res.ok) {
throw new RetryableError("Payment failed", {
maxAttempts: 5,
retryInterval: 2000,
});
}
return res.json();
});| Option | Type | Description |
|---|---|---|
maxAttempts | number | Total number of times the step executes (including the first attempt) |
retryInterval | number | Milliseconds between retry attempts |
How retries work
When a RetryableError is thrown:
- The runtime caches the error with
done: false, indicating the step is incomplete. - The runtime schedules a wake-up after
retryIntervalmilliseconds. - The worker process terminates.
- On the next invocation, the runtime replays cached steps, reaches the incomplete step, clears the cached error, and re-executes the function.
- This repeats until the function succeeds or
maxAttemptsis reached.
When maxAttempts is exhausted, the error is thrown into the workflow generator. You can catch it with a standard try/catch:
try {
yield* step.run(async () => {
throw new RetryableError("flaky", { maxAttempts: 3, retryInterval: 1000 });
});
} catch (err) {
// all 3 attempts failed
yield* step.run(() => markAsFailed());
}Non-retryable errors
Any error that is not a RetryableError terminates the step immediately and throws into the workflow — no retries, no scheduling. The error is cached with done: true.
yield* step.run(() => {
throw new Error("fatal"); // no retry, thrown immediately
});Retry via polling
step.poll is a higher-level primitive that uses RetryableError internally. It retries a predicate at a fixed interval:
yield* step.poll(
{ retryInterval: 1000, maxAttempts: 10 },
() => isReady()
);If isReady() returns false, the poll throws a RetryableError with the configured policy. If it returns true, the step completes. If it throws a regular error, the step fails without retrying.