Pluggable retry decisions via retryPolicy
The default retry strategy is retryDelay x 2attempt. When you need smarter behaviour - honouring Retry-After on 429/503, classifying permanent vs transient errors, jitter to avoid thundering herd, or capping at a wall-clock budget - pass a retryPolicy function that returns the desired delay (or false to abort).
What you should see: transient failures retried automatically with increasing delays, up to 5 attempts, instead of failing on the first error. Auto-upload is off so you can start it deliberately.
Drag & drop files here, or paste from clipboard
Try it: point the uploader at a server that returns
503 Retry-After: 5 and the policy waits 5 seconds. Point it at a 404 endpoint and it aborts on the first failure with no retries.
Function signature
retryPolicy: function(attempt, error, ctx) {
// attempt = 1-based count of the NEXT try (1 on first failure) // error = the Error that triggered the retry consideration // ctx = { task, kind: 'task'|'chunk'|'control', index? } // returns: number ms | false (abort) | true (default)
} Recipe library
// 1. Honor Retry-After on 429/503
retryPolicy: (attempt, err) => err.retryAfter ? err.retryAfter * 1000 : true
// 2. Never retry permanent errors
retryPolicy: (attempt, err) => /HTTP (401|403|404|410|422)/.test(err.message) ? false : true
// 3. Wall-clock budget (5 minutes)
const deadline = Date.now() + 5 * 60_000;
retryPolicy: () => Date.now() > deadline ? false : true
// 4. Jittered exponential
retryPolicy: (attempt) => {
const base = 1000 * Math.pow(2, attempt - 1);
return base + Math.random() * base * 0.5;
} Safety
- Returned delays are capped at 10 minutes internally to prevent runaway sleeps.
- Total attempts still respect
options.retries. - Throwing policies fall back gracefully to default exponential - your retries don't break upload.