transloadit/uppy · error · S3NetworkError
NETWORK
NETWORK
Error message
Network error during S3 request
What it means
When the underlying XHR fails at the network layer, s3mini inspects the error's request: if `xhr.status === 0` (request never completed — no HTTP response), it wraps the failure in S3NetworkError with code 'NETWORK'. This distinguishes connectivity/DNS/CORS-blocked requests from actual HTTP error responses (non-2xx) which are handled separately.
Source
Thrown at packages/@uppy/aws-s3/src/s3-client/S3mini.ts:331
url,
method: request.method,
data,
onProgress,
signal,
contentType,
})
return { xhr, url }
} catch (err: unknown) {
// NetworkError or errors with attached XHR (from onAfterResponse throws)
if (
err instanceof Error &&
'request' in err &&
err.request instanceof XMLHttpRequest
) {
const xhr = err.request as XMLHttpRequest
if (xhr.status === 0) {
throw new U.S3NetworkError(
'Network error during S3 request',
'NETWORK',
err,
)
}
// HTTP errors (non-2xx responses from NetworkError)
const parsedBody = this._parseErrorXml(
(name: string) => xhr.getResponseHeader(name),
xhr.responseText,
)
const serviceCode =
xhr.getResponseHeader('x-amz-error-code') ?? parsedBody.svcCode
// If expired token error and using getCredentials, clear cache and retry once
if (
shouldRetryCredentials &&
this.getCredentials != null &&
serviceCode != null &&View on GitHub (pinned to 5d4dedd02a)
Solutions
- Open devtools Network tab: a failed OPTIONS preflight points to CORS config; a failed DNS/connect points to the endpoint/offline.
- For CORS, ensure the bucket allows your origin, the methods (PUT/POST/GET), and required headers (content-type, x-amz-*).
- Verify the endpoint URL is reachable from the client environment (curl the URL, check TLS/mixed content).
- Retry with backoff for transient network drops — S3NetworkError is safe to retry, especially idempotent part uploads.
Example fix
// before
try { await s3.uploadPart(...) } catch (e) { throw e }
// after
try { await s3.uploadPart(...) } catch (e) {
if (e.code === 'NETWORK') await retryWithBackoff(() => s3.uploadPart(...))
else throw e
} Defensive patterns
Strategy: retry
Type guard
const isNetworkError = (e: unknown): e is { code: 'NETWORK' } =>
typeof e === 'object' && e !== null && (e as any).code === 'NETWORK' Try / catch
async function uploadWithRetry(fn: () => Promise<unknown>, tries = 3) {
for (let i = 0; i < tries; i++) {
try { return await fn() } catch (e) {
if ((e as any)?.code === 'NETWORK' && i < tries - 1) {
await new Promise((r) => setTimeout(r, 2 ** i * 500)); continue
}
throw e
}
}
} Prevention
- Verify bucket CORS (origin, methods, x-amz-* headers) before shipping browser uploads.
- Retry network-coded errors with exponential backoff; part uploads are idempotent.
- Ensure the endpoint is HTTPS when the page is HTTPS to avoid mixed-content failures.
When it happens
Trigger: Device offline or connection dropped mid-request; DNS failure for the endpoint; CORS preflight blocked (browser reports status 0); TLS certificate errors; proxy/firewall resetting the connection. Any XHR that terminates without an HTTP status.
Common situations: Browser uploads blocked by missing/incorrect CORS config on the bucket (preflight failure shows as status 0); flaky mobile networks during multipart uploads; corporate proxies blocking S3 domains; wrong endpoint hostname that doesn't resolve; mixed-content (https page → http endpoint).
Related errors
- [s3mini] Missing ETag in uploadPart response headers
- AbortError
- Either signRequest or getCredentials must be provided
- signRequest must be a function
- [s3mini] endpoint must be a non-empty string
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/30cafb5aabb996f5.
Report an issue: GitHub.