Version v1.x
Error Handling
Available in
.NET
Node.js
Python
Failure categories, retry behavior, and implementation guidance for robust handlers.
Error handling in DurableStack is run-centric: each run either succeeds, retries, or becomes terminally failed.
Failure categories
- Transient failures: network timeouts, temporary dependency outages, throttling.
- Persistent logic/data failures: invalid payload, invariant violations, unrecoverable contract errors.
Retry interaction
- Retry eligibility:
Attempt < MaxAttempts. - Retry timing: fixed delay or backoff based on job/runtime settings.
- Terminal failure: run marked
failedwhen attempts are exhausted.
Recommended handler patterns
- Keep handlers idempotent.
- Throw for truly failed execution paths.
- Avoid swallowing exceptions that should drive retries.
- Log with
RunId,JobName, andAttemptfor traceability.
Example
public async Task ExecuteAsync(JobContext context, CancellationToken cancellationToken)
{
try
{
await _externalApiClient.PushAsync(cancellationToken);
}
catch (HttpRequestException ex)
{
_logger.LogWarning(ex,
"Transient external call failure. Job={JobName} RunId={RunId} Attempt={Attempt}",
context.JobName,
context.RunId,
context.Attempt);
throw;
}
}
runtime.registerJob("push-external-update", async (context) => {
try {
await externalApiClient.push();
} catch (error) {
logger.warn({
error,
jobName: context.jobName,
runId: context.runId,
attempt: context.attempt
}, "Transient external call failure");
throw error;
}
});
Operational recommendations
- Monitor retry and failure rates over time.
- Keep max attempts lower for side effects that are hard to deduplicate.
- Use backoff for unstable dependencies to reduce cascading load.