The "StorageApiError: Object not found" error occurs when Supabase Storage cannot locate a file or object you're trying to access. This typically happens when referencing files that don't exist, have been deleted, or have incorrect paths. The fix involves verifying file paths, checking bucket permissions, and ensuring proper file upload procedures.
The "StorageApiError: Object not found" is a client-side error from the Supabase JavaScript/TypeScript SDK that occurs when you attempt to access a storage object (file) that doesn't exist in the specified bucket. This error is thrown by the Supabase Storage API when a requested file path cannot be resolved to an actual object in your storage bucket. Unlike server-side errors that might indicate infrastructure problems, this error typically indicates a client-side issue with your application logic - you're trying to access a file that either: 1. Was never uploaded successfully 2. Has been deleted or moved 3. Has a different path than what you're requesting 4. Exists in a different bucket than you're querying The error is part of Supabase's client-side error handling and helps developers identify issues with their file management logic before making unnecessary API calls.
First, double-check the exact path you're using to reference the file. The most common cause is a simple typo or incorrect path construction.
// Example: Check your file path
const fileName = 'profile-pictures/user-123.jpg';
const bucketName = 'avatars';
// Common mistakes:
// 1. Missing file extension
const wrongPath = 'profile-pictures/user-123'; // Missing .jpg
// 2. Incorrect bucket
const wrongBucket = 'avatar'; // Should be 'avatars'
// 3. Extra slashes or incorrect path structure
const messyPath = '/avatars//profile-pictures/user-123.jpg'; // Extra slashes
// Correct usage:
const { data, error } = await supabase.storage
.from(bucketName)
.download(fileName);Use the Supabase dashboard to browse your storage buckets and verify the exact file paths.
Use the Supabase Storage API to list files in the bucket and verify the file exists:
// List all files in the bucket to see what's available
const { data: files, error } = await supabase.storage
.from('your-bucket-name')
.list('folder-path', {
limit: 100,
offset: 0,
sortBy: { column: 'name', order: 'asc' }
});
if (error) {
console.error('Error listing files:', error);
} else {
console.log('Files in bucket:', files);
// Check if your file is in the list
const fileExists = files.some(file => file.name === 'your-file.jpg');
console.log('File exists:', fileExists);
}You can also check the Supabase dashboard directly: go to Storage → select your bucket → browse to the folder.
If you recently uploaded the file, ensure the upload completed successfully:
// Example upload with proper error handling
const uploadFile = async (file) => {
const { data, error } = await supabase.storage
.from('bucket-name')
.upload('folder/' + file.name, file, {
cacheControl: '3600',
upsert: false // Set to true if you want to overwrite existing files
});
if (error) {
console.error('Upload failed:', error);
// Handle specific error types
if (error.message.includes('already exists')) {
console.log('File already exists, consider using upsert: true');
}
return null;
}
console.log('Upload successful:', data.path);
return data.path; // Save this path for future reference
};
// Always check the upload result
const filePath = await uploadFile(myFile);
if (!filePath) {
console.error('File was not uploaded successfully');
}Common upload issues:
- File size exceeds bucket limits
- Network interruptions during upload
- Insufficient permissions for the bucket
- File name conflicts (when upsert: false)
If your bucket has RLS enabled, ensure your user has permission to access the file:
-- Check your RLS policies in the Supabase SQL editor
-- Example policy that might be too restrictive:
CREATE POLICY "Users can view their own files"
ON storage.objects FOR SELECT
USING (auth.uid() = owner);
-- If the file doesn't have an owner set or the owner doesn't match,
-- the file won't be accessible.
-- You might need a more permissive policy:
CREATE POLICY "Anyone can view public files"
ON storage.objects FOR SELECT
USING (bucket_id = 'public-bucket-name');To test RLS issues:
1. Temporarily disable RLS on the bucket (in production, create a test bucket instead)
2. Try accessing the file again
3. If it works, your RLS policies need adjustment
File paths with spaces or special characters need proper URL encoding:
// Problem: File with spaces in name
const problemFile = 'my document.pdf'; // Contains space
// Solution 1: Encode the path
const encodedPath = encodeURIComponent('my document.pdf');
// Or use the storage API which handles encoding internally
// Solution 2: Use a consistent naming convention
// Replace spaces and special characters
const safeFileName = file.name
.toLowerCase()
.replace(/s+/g, '-')
.replace(/[^a-z0-9-.]/g, '');
// Solution 3: When constructing URLs manually:
const publicUrl = supabase.storage
.from('bucket')
.getPublicUrl('path/with spaces/file.pdf');
// The getPublicUrl method handles encoding for youBest practice: Normalize all file names before uploading to avoid encoding issues.
Add robust error handling to gracefully handle missing files:
const getFileWithFallback = async (filePath, fallbackPath) => {
try {
const { data, error } = await supabase.storage
.from('bucket')
.download(filePath);
if (error) {
if (error.message.includes('Object not found')) {
console.warn('File ' + filePath + ' not found, using fallback');
// Try fallback file
return await supabase.storage
.from('bucket')
.download(fallbackPath);
}
throw error;
}
return { data, error: null };
} catch (err) {
console.error('Error in getFileWithFallback:', err);
return { data: null, error: err };
}
};
// Usage with default avatar example
const userAvatar = await getFileWithFallback(
'avatars/' + userId + '.jpg',
'avatars/default.jpg'
);Also consider:
- Adding loading states while files load
- Using placeholder images for missing files
- Logging missing file occurrences for debugging
## Deep Dive: Supabase Storage Architecture
Supabase Storage is built on top of PostgreSQL and uses a combination of:
1. storage.objects table: Metadata about files (path, size, owner, etc.)
2. storage.buckets table: Bucket configurations and RLS policies
3. External storage: Actual file content stored in object storage (S3-compatible)
When you get "Object not found", it could mean:
- The record exists in storage.objects but the actual file is missing from object storage
- The record was deleted from storage.objects but cached references remain
- RLS policies are preventing access even though the file exists
## Common Edge Cases
1. File Deletion Race Conditions: If you delete a file and immediately try to access it, you might get cached results. Implement retry logic with exponential backoff.
2. Bucket Migration: If you move files between buckets, update all references. Consider using a mapping table for file locations.
3. CDN Caching: Public URLs might be cached by CDN. Use cache-busting query parameters or versioned file paths.
4. File Versioning: If using file versioning, ensure you're referencing the correct version.
## Monitoring and Debugging
1. Enable detailed logging:
supabase.storage.from('bucket').download('path', {
headers: { 'X-Client-Info': 'my-app/v1.0' }
});2. Check Supabase logs in the dashboard under Logs → Storage
3. Use the Network tab in browser DevTools to inspect API requests and responses
## Performance Considerations
- Use getPublicUrl() for public files instead of download() to reduce API calls
- Implement client-side caching for frequently accessed files
- Consider using signed URLs for time-limited access to private files
email_conflict_identity_not_deletable: Cannot delete identity because of email conflict
How to fix "Cannot delete identity because of email conflict" in Supabase
mfa_challenge_expired: MFA challenge has expired
How to fix "mfa_challenge_expired: MFA challenge has expired" in Supabase
conflict: Database conflict, usually related to concurrent requests
How to fix "database conflict usually related to concurrent requests" in Supabase
phone_exists: Phone number already exists
How to fix "phone_exists" in Supabase
StorageApiError: resource_already_exists
StorageApiError: Resource already exists