Error Handling
Learn how to handle errors gracefully in your Reimage API integration.
HTTP Status Codes
| Code | Meaning | Common Causes |
|---|---|---|
| 200 | Success | Request completed successfully |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Storage limit exceeded, feature not enabled |
| 404 | Not Found | Image or resource doesn't exist |
| 500 | Internal Server Error | Server error (rare) |
Error Response Format
Errors are returned as JSON:
json
{
"error": "Error message describing what went wrong"
}Common Errors
401 Unauthorized
Cause: Missing or invalid API key
json
{
"error": "Unauthorized"
}Solution:
javascript
// ✅ Correct
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
// ❌ Wrong - missing Bearer prefix
headers: {
'Authorization': 'YOUR_API_KEY'
}
// ❌ Wrong - invalid header name
headers: {
'API-Key': 'YOUR_API_KEY'
}403 Storage Limit Exceeded
Cause: You've reached your storage quota
json
{
"error": "Storage limit exceeded"
}Solution:
javascript
// Check storage before upload
async function safeUpload(file) {
const user = await fetch('https://api.reimage.dev/user/', {
headers: { 'Authorization': `Bearer ${API_KEY}` }
}).then(r => r.json());
const fileSizeKB = file.size / 1024;
const available = user.storage_limit - user.storage_used;
if (fileSizeKB > available) {
throw new Error(
`Not enough storage. Need ${fileSizeKB}KB, have ${available}KB available`
);
}
// Proceed with upload
return await uploadImage(file);
}403 AI Analysis Not Enabled
Cause: Trying to use AI search without enabling it
json
{
"error": "AI analysis not enabled for this user"
}Solution: Contact support to enable AI analysis feature
403 OpenAI API Key Not Configured
Cause: AI search requires OpenAI API key
json
{
"error": "OpenAI API key not configured"
}Solution: Add your OpenAI API key in account settings
404 Image Not Found
Cause: Image doesn't exist or wrong object ID
json
{
"error": "Image not found"
}Solution:
javascript
async function getImageSafely(objectId) {
try {
const response = await fetch(
`https://api.reimage.dev/delete/${objectId}`,
{
method: 'DELETE',
headers: { 'Authorization': `Bearer ${API_KEY}` }
}
);
if (response.status === 404) {
console.log('Image already deleted or never existed');
return null;
}
return await response.json();
} catch (error) {
console.error('Error:', error);
throw error;
}
}Error Handling Patterns
JavaScript / TypeScript
javascript
async function uploadWithErrorHandling(file) {
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('https://api.reimage.dev/upload/', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REIMAGE_API_KEY}`
},
body: formData
});
// Handle specific status codes
if (response.status === 401) {
throw new Error('Invalid API key. Please check your credentials.');
}
if (response.status === 403) {
const error = await response.json();
if (error.error.includes('Storage limit')) {
throw new Error('Storage limit exceeded. Please upgrade your plan.');
}
throw new Error(error.error);
}
if (!response.ok) {
throw new Error(`Upload failed with status: ${response.status}`);
}
return await response.json();
} catch (error) {
// Network errors
if (error instanceof TypeError && error.message.includes('fetch')) {
throw new Error('Network error. Please check your connection.');
}
throw error;
}
}Python
python
import requests
from requests.exceptions import RequestException
def upload_with_error_handling(file_path):
try:
with open(file_path, 'rb') as f:
files = {'file': f}
headers = {'Authorization': f'Bearer {API_KEY}'}
response = requests.post(
'https://api.reimage.dev/upload/',
files=files,
headers=headers
)
# Handle specific status codes
if response.status_code == 401:
raise Exception('Invalid API key')
if response.status_code == 403:
error = response.json()
if 'Storage limit' in error.get('error', ''):
raise Exception('Storage limit exceeded')
raise Exception(error.get('error', 'Forbidden'))
if response.status_code == 404:
raise Exception('Resource not found')
response.raise_for_status()
return response.json()
except RequestException as e:
raise Exception(f'Network error: {str(e)}')
except FileNotFoundError:
raise Exception(f'File not found: {file_path}')PHP
php
<?php
function uploadWithErrorHandling($filePath) {
if (!file_exists($filePath)) {
throw new Exception("File not found: $filePath");
}
$cfile = new CURLFile($filePath);
$postData = ['file' => $cfile];
$ch = curl_init('https://api.reimage.dev/upload/');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . getenv('REIMAGE_API_KEY')
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
// Handle network errors
if ($curlError) {
throw new Exception("Network error: $curlError");
}
// Handle HTTP errors
switch ($httpCode) {
case 200:
return json_decode($response, true);
case 401:
throw new Exception('Invalid API key');
case 403:
$error = json_decode($response, true);
throw new Exception($error['error'] ?? 'Forbidden');
case 404:
throw new Exception('Resource not found');
default:
throw new Exception("Request failed with status: $httpCode");
}
}
?>React Error Handling
jsx
import { useState } from 'react';
function ImageUploader() {
const [error, setError] = useState(null);
const [uploading, setUploading] = useState(false);
const handleUpload = async (file) => {
setError(null);
setUploading(true);
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('https://api.reimage.dev/upload/', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_REIMAGE_API_KEY}`
},
body: formData
});
if (response.status === 401) {
throw new Error('Authentication failed. Please check your API key.');
}
if (response.status === 403) {
const errorData = await response.json();
if (errorData.error.includes('Storage limit')) {
throw new Error('You\'ve reached your storage limit. Please upgrade your plan or delete some images.');
}
throw new Error(errorData.error);
}
if (!response.ok) {
throw new Error(`Upload failed (${response.status})`);
}
const data = await response.json();
// Handle success...
} catch (err) {
setError(err.message);
} finally {
setUploading(false);
}
};
return (
<div>
<input
type="file"
onChange={(e) => handleUpload(e.target.files[0])}
disabled={uploading}
/>
{uploading && <p>Uploading...</p>}
{error && (
<div className="error-message" style={{ color: 'red' }}>
<strong>Error:</strong> {error}
</div>
)}
</div>
);
}Retry Logic
javascript
async function uploadWithRetry(file, maxRetries = 3) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await uploadImage(file);
} catch (error) {
lastError = error;
// Don't retry on client errors (4xx)
if (error.message.includes('401') || error.message.includes('403')) {
throw error;
}
// Wait before retrying (exponential backoff)
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error(`Upload failed after ${maxRetries} retries: ${lastError.message}`);
}Timeout Handling
javascript
async function uploadWithTimeout(file, timeoutMs = 30000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('https://api.reimage.dev/upload/', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REIMAGE_API_KEY}`
},
body: formData,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`Upload failed: ${response.status}`);
}
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error(`Upload timed out after ${timeoutMs}ms`);
}
throw error;
}
}Validation Before Upload
javascript
function validateFile(file) {
const maxSize = 10 * 1024 * 1024; // 10MB
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
if (file.size > maxSize) {
throw new Error(`File too large. Maximum size is ${maxSize / 1024 / 1024}MB`);
}
if (!allowedTypes.includes(file.type)) {
throw new Error(`Invalid file type. Allowed: ${allowedTypes.join(', ')}`);
}
return true;
}
// Usage
try {
validateFile(file);
await uploadImage(file);
} catch (error) {
console.error('Validation error:', error.message);
}Global Error Handler
javascript
// Set up global error handler
window.addEventListener('unhandledrejection', (event) => {
if (event.reason?.message?.includes('reimage.dev')) {
console.error('Reimage API Error:', event.reason);
// Log to error tracking service
// trackError(event.reason);
// Show user-friendly message
showNotification('An error occurred. Please try again.');
event.preventDefault();
}
});Best Practices
- Always check response status before parsing JSON
- Provide user-friendly error messages instead of technical details
- Log errors for debugging but don't expose sensitive info
- Validate input before making API calls
- Handle network errors separately from API errors
- Use retry logic for transient failures
- Set timeouts for long-running operations
- Check storage limits before uploads
Next Steps
- Upload API - Upload endpoint details
- User API - Check storage usage
- Authentication - API key setup