This error occurs when a Firebase Storage operation (upload, download, or delete) takes too long and exceeds the maximum retry time limit, typically after 10 minutes of retries due to network issues or large file sizes.
The `storage/retry-limit-exceeded` error indicates that Firebase Storage's built-in retry mechanism has reached its maximum time limit while attempting to complete an operation. Firebase Storage automatically retries failed operations to handle transient network issues, but when an operation repeatedly fails or takes too long, it eventually gives up and throws this error. By default, Firebase Storage will retry operations for up to 10 minutes (600,000 milliseconds) before throwing this error. The retry mechanism uses exponential backoff to progressively wait longer between retry attempts. This error most commonly occurs during upload or download operations of large files, especially when network connectivity is poor or intermittent. The error can happen with any storage operation including uploads (putFile, putBytes), downloads (getDownloadURL, getData), and delete operations. When you see this error, it means Firebase has exhausted all retry attempts within the configured time window.
Configure Firebase Storage to allow more time for large file operations by increasing the maximum retry time.
For Web/JavaScript:
import { getStorage } from 'firebase/storage';
const storage = getStorage();
// Set max upload retry time to 20 minutes (1200000ms)
storage.maxUploadRetryTime = 1200000;
// Set max download retry time to 20 minutes
storage.maxOperationRetryTime = 1200000;For Android:
FirebaseStorage storage = FirebaseStorage.getInstance();
// Set max upload retry time to 20 minutes
storage.setMaxUploadRetryTimeMillis(1200000);
// Set max operation retry time to 20 minutes
storage.setMaxOperationRetryTimeMillis(1200000);For React Native Firebase:
import storage from '@react-native-firebase/storage';
const reference = storage().ref('path/to/file');
// Set timeout on the specific task
reference.setMaxUploadRetryTime(1200000);Adjust the timeout values based on your expected file sizes and typical network conditions.
Add custom retry logic that catches the error and retries the operation with exponential backoff.
async function uploadWithRetry(file, path, maxRetries = 3) {
const storage = getStorage();
const storageRef = ref(storage, path);
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const uploadTask = uploadBytesResumable(storageRef, file);
// Monitor upload progress
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(`Upload is ${progress}% done`);
}
);
await uploadTask;
console.log('Upload successful');
return uploadTask.snapshot;
} catch (error) {
if (error.code === 'storage/retry-limit-exceeded') {
console.log(`Retry ${attempt} of ${maxRetries} failed`);
if (attempt === maxRetries) {
throw new Error('Upload failed after maximum retries');
}
// Exponential backoff: wait longer between each retry
const waitTime = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, waitTime));
} else {
throw error; // Re-throw non-retry errors
}
}
}
}For very large files, implement chunked uploads to avoid timeout issues.
import { getStorage, ref, uploadBytesResumable } from 'firebase/storage';
async function uploadLargeFile(file, path) {
const storage = getStorage();
const chunkSize = 5 * 1024 * 1024; // 5MB chunks
if (file.size <= chunkSize) {
// Small file, upload normally
const storageRef = ref(storage, path);
return uploadBytesResumable(storageRef, file);
}
// For large files, use resumable upload with pause/resume capability
const storageRef = ref(storage, path);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(`Upload is ${progress}% done`);
},
(error) => {
console.error('Upload error:', error);
},
() => {
console.log('Upload completed successfully');
}
);
return uploadTask;
}Alternatively, consider using Firebase Cloud Functions to handle large file uploads server-side where network connectivity is more reliable.
Add network status monitoring to pause/resume uploads when connectivity changes.
let uploadTask;
// Detect network status changes
window.addEventListener('online', () => {
if (uploadTask && uploadTask.snapshot.state === 'paused') {
uploadTask.resume();
console.log('Network restored, resuming upload');
}
});
window.addEventListener('offline', () => {
if (uploadTask && uploadTask.snapshot.state === 'running') {
uploadTask.pause();
console.log('Network lost, pausing upload');
}
});
// Start upload with pause/resume capability
function startUpload(file, path) {
const storage = getStorage();
const storageRef = ref(storage, path);
uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on('state_changed',
(snapshot) => {
console.log(`Progress: ${snapshot.bytesTransferred}/${snapshot.totalBytes}`);
},
(error) => {
if (error.code === 'storage/retry-limit-exceeded') {
console.error('Upload timeout exceeded');
}
},
() => {
console.log('Upload complete');
uploadTask = null;
}
);
return uploadTask;
}For mobile apps, detect when the device switches between WiFi and cellular to proactively manage uploads.
Check your network connection and ensure file sizes are appropriate for your timeout settings.
// Calculate minimum required upload speed
function calculateRequiredSpeed(fileSizeBytes, timeoutMs) {
const fileSizeMB = fileSizeBytes / (1024 * 1024);
const timeoutMinutes = timeoutMs / (60 * 1000);
const requiredMbps = (fileSizeMB * 8) / (timeoutMinutes * 60);
return {
fileSizeMB: fileSizeMB.toFixed(2),
timeoutMinutes: timeoutMinutes.toFixed(1),
requiredMbps: requiredMbps.toFixed(2)
};
}
// Example: 100MB file with 10-minute timeout
const requirements = calculateRequiredSpeed(100 * 1024 * 1024, 600000);
console.log(`Need at least ${requirements.requiredMbps} Mbps to upload ${requirements.fileSizeMB}MB in ${requirements.timeoutMinutes} minutes`);Consider implementing client-side file size validation before attempting uploads:
const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
if (file.size > MAX_FILE_SIZE) {
alert('File too large. Please upload files smaller than 50MB.');
return;
}Platform-Specific Timeout Defaults:
The default maximum retry times vary slightly across Firebase SDKs:
- Web SDK: 10 minutes (600,000ms) for uploads and downloads
- Android SDK: 10 minutes for uploads, 10 minutes for other operations
- iOS SDK: Similar 10-minute defaults with platform-specific configurations
Resumable Upload Sessions:
Firebase Storage uses resumable upload sessions for files larger than 256KB. These sessions remain valid for 1 week, allowing you to resume interrupted uploads even after app restarts. However, the retry-limit-exceeded error is based on the cumulative retry time within a single upload attempt, not the session lifetime.
Server-Side Considerations:
If you're experiencing this error frequently, consider:
- Using Firebase Cloud Functions to handle uploads server-side where network is more reliable
- Implementing a signed URL approach where clients upload directly to Cloud Storage buckets with custom timeout configurations
- Checking Firebase Status Dashboard for any ongoing service issues
Mobile App Best Practices:
For mobile applications:
- Only allow uploads on WiFi for large files
- Implement background upload tasks that persist across app sessions
- Show clear progress indicators and allow users to cancel/retry manually
- Store upload metadata locally to resume failed uploads
- Consider using WorkManager (Android) or Background Tasks (iOS) for reliable large file uploads
Network Optimization:
The retry mechanism in Firebase Storage uses exponential backoff, starting with short delays and progressively increasing. For very large files on slow connections, even aggressive timeout settings may not be sufficient. In these cases, architectural changes (compression, resolution reduction for images/videos, or chunked processing) may be necessary.
messaging/UNSPECIFIED_ERROR: No additional information available
How to fix "messaging/UNSPECIFIED_ERROR: No additional information available" in Firebase Cloud Messaging
App Check: reCAPTCHA Score Too Low
App Check reCAPTCHA Score Too Low
storage/invalid-url: Invalid URL format for Cloud Storage reference
How to fix invalid URL format in Firebase Cloud Storage
auth/missing-uid: User ID identifier required
How to fix "auth/missing-uid: User ID identifier required" in Firebase
auth/invalid-argument: Invalid parameter passed to method
How to fix "auth/invalid-argument: Invalid parameter passed to method" in Firebase