Skip to content

Error Handling

Learn how to handle errors gracefully in your Reimage API integration.

HTTP Status Codes

CodeMeaningCommon Causes
200SuccessRequest completed successfully
401UnauthorizedMissing or invalid API key
403ForbiddenStorage limit exceeded, feature not enabled
404Not FoundImage or resource doesn't exist
500Internal Server ErrorServer 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

  1. Always check response status before parsing JSON
  2. Provide user-friendly error messages instead of technical details
  3. Log errors for debugging but don't expose sensitive info
  4. Validate input before making API calls
  5. Handle network errors separately from API errors
  6. Use retry logic for transient failures
  7. Set timeouts for long-running operations
  8. Check storage limits before uploads

Next Steps

Released under the MIT License.