remotion-dev/remotion · error · Error
Timed out downloading remote asset
Error message
Timed out downloading remote asset
What it means
Thrown by downloadRemoteAsset in @remotion/browser-studio when the fetch is aborted by the built-in timeout (remoteAssetDownloadTimeout via AbortController) — the asset server did not respond within the allowed window, either for the initial response or while streaming the body. The AbortError is translated to this message; the promise rejects directly.
Source
Thrown at packages/browser-studio/src/download-remote-asset.ts:60
throw new Error('Remote asset URLs cannot include credentials');
}
const abortController = new AbortController();
const timeout = setTimeout(() => {
abortController.abort();
}, remoteAssetDownloadTimeout);
let contents: Uint8Array;
try {
let response: Response;
try {
response = await fetch(url, {
headers: {accept: remoteAssetAcceptHeader},
signal: abortController.signal,
});
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
throw new Error('Timed out downloading remote asset');
}
throw new Error(
`Could not fetch remote asset. The URL may not allow cross-origin requests (CORS): ${
error instanceof Error ? error.message : String(error)
}`,
);
}
if (!response.ok) {
throw new Error(`Could not download remote asset: ${response.status}`);
}
const contentLength = response.headers.get('content-length');
if (contentLength !== null && Number(contentLength) > maxRemoteAssetSize) {
abortController.abort();
throw new Error('Remote asset exceeds the 50MB size limit');
}View on GitHub (pinned to 10db9de073)
Solutions
- Retry the import — transient timeouts often succeed on a second attempt
- Host the asset on a faster CDN closer to the user, or pre-compress/resize it
- Check the URL opens quickly in a browser tab on the same network
- If it consistently times out, download the asset manually and add it via writeStaticFile
Example fix
// before
await operations.downloadRemoteAsset({url}); // may reject: Timed out downloading remote asset
// after
async function importWithRetry(url: string, attempts = 2) {
for (let i = 0; i <= attempts; i++) {
try {
return await operations.downloadRemoteAsset({url});
} catch (e) {
const isTimeout = e instanceof Error && e.message === 'Timed out downloading remote asset';
if (!isTimeout || i === attempts) throw e;
}
}
throw new Error('unreachable');
} Defensive patterns
Strategy: retry
Validate before calling
const reachable = await fetch(url, {method: 'HEAD', signal: AbortSignal.timeout(5000)}).then((r) => r.ok).catch(() => false);
if (!reachable) throw new Error('Asset server not responding — try again later'); Try / catch
const isTimeout = (e: unknown) => e instanceof Error && e.message === 'Timed out downloading remote asset';
try {
result = await operations.downloadRemoteAsset({url});
} catch (error) {
if (isTimeout(error) && attempt < maxAttempts) { await backoff(attempt); return download(attempt + 1); }
throw error;
} Prevention
- Retry once or twice with backoff — timeouts are frequently transient
- Import from CDNs with low latency to your users
- Pre-compress oversized or slow assets instead of importing originals
When it happens
Trigger: Importing a large image from a slow or distant server; server stalls mid-download (the body-streaming loop is also covered by the same timeout); client network degraded (offline, throttled); server takes long to generate the asset on the fly.
Common situations: Users on slow connections importing multi-megapixel images; origin servers behind slow CDN cold starts; mobile networks; localhost dev with a stalled mock server.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Could not fetch remote asset. The URL may not allow cross-or
- Could not download remote asset: ${response.status}
- Only HTTP(S) URLs can be imported
- Remote asset URLs cannot include credentials
- Remote asset exceeds the 50MB size limit
AI-assisted analysis of remotion-dev/remotion@10db9de073 (2026-08-22).
Data as JSON: /api/errors/f53d269308ee4376.
Report an issue: GitHub.