onRetry
Runs each time the SDK schedules a retry for a single-operation call, with the upcoming attempt, its delay, and the triggering error.
A constructor hook that runs each time the SDK schedules a retry for a single-operation call, with the upcoming attempt, the delayMs before it, and the error that triggered it. It never fires on the first attempt, for non-retryable errors, or for stream uploads (which aren't retried). The array forms never fire it either — they settle as a single aggregated onAction event for the whole call. See Retries for what counts as retryable.
const files = new Files({
adapter: s3({ bucket: "uploads" }),
retries: 3,
hooks: {
onRetry(event) {
logger.warn("files retry", {
action: event.type,
key: event.key,
attempt: `${event.attempt}/${event.maxRetries}`,
delayMs: event.delayMs,
code: event.error.code,
});
},
},
});It fires before the wait, so delayMs is the backoff the SDK is about to sleep, not one already spent. error is the FilesError from the attempt that just failed - always a retryable Provider failure, since the deterministic codes are never retried.
Watching for exhaustion
attempt counts up from 1, and maxRetries is the ceiling for this call - so attempt === maxRetries is the last retry the SDK will schedule. If that one also fails, no further onRetry fires and the call settles through onError and onAction. Use the comparison to count calls that burn through their whole retry budget.
hooks: {
onRetry(event) {
metrics.increment("files.retry", { action: event.type });
if (event.attempt === event.maxRetries) {
metrics.increment("files.retry.exhausted", { action: event.type });
}
},
},A steady stream of retries on one type is usually a sign of a throttling or availability problem with that provider - surfacing event.error.code alongside the count makes the cause visible.
Like the other hooks, onRetry is fire-and-forget: it can't change the backoff, cancel the retry, or fail the call - it only observes.
Prop
Type