Retry policy: failed runs (including timeouts) are retried with exponential backoff (delay = min(backoffMs * backoffMultiplier^(retry-1), maxRetryDelayMs), optionally jittered) up to maxRetries retries after the initial attempt (#3494). Omit the block for a single attempt; declaring it without maxRetries also means no retry since 17.0.0 (#4661) — state a count to opt in.
timeout
integer
optional
Per-attempt time limit in milliseconds; an over-limit run is recorded with execution status "timeout" (#3494). The in-flight handler is abandoned, not forcibly cancelled. Omit for no time limit.
Retry attempts after the initial one. 0 (the default) means no retry — state a count to opt in.
backoffMs
integer
✅
Base delay before the first retry (ms); subsequent delays multiply by backoffMultiplier
backoffMultiplier
number
✅
Exponential backoff multiplier; 1 (the default) keeps the delay flat
maxRetryDelayMs
integer
✅
Ceiling for a single backoff delay (ms)
jitter
boolean
✅
Randomize each delay within [50%, 100%] of its computed value — spreads a thundering herd of simultaneous retries
retryDelayMs
never
optional
[REMOVED] retryDelayMs was removed in @objectstack/spec 17.0.0 (#4661, #4964) — the retry policy now has ONE spelling for its base delay across every surface that carries it: job.retryPolicy, a try_catch node's retry and flow.errorHandling. Rename the key to backoffMs; the value (milliseconds before the first retry) is unchanged. Run os migrate meta --from 16 to rewrite existing sources automatically.