Troubleshooting Common API Errors

400 – Bad Request

Your request is malformed or contains invalid data.

Common causes:

  • Missing required fields in request body
  • Invalid JSON syntax
  • Wrong data types (string instead of integer)
  • Sending body with GET request
  • Invalid query parameters

Example error response:

{
  "error": "Bad Request",
  "message": "The issue_id field is required.",
  "status": 400
}

How to fix:

// ❌ Bad: Missing required field
POST /api/user/collection
{
  "condition": "NM"
  // Missing issue_id!
}

// ✅ Good: All required fields present
POST /api/user/collection
{
  "issue_id": 12345,
  "condition": "NM"
}

Debugging checklist:

  • Validate JSON syntax with a linter
  • Check API docs for required fields
  • Ensure data types match (numbers as numbers, not strings)
  • Don't send request body with GET requests

401 – Unauthorized

You are not authenticated, or your token is invalid/expired.

Common causes:

  • Missing Authorization header
  • Invalid or expired token
  • Token was revoked
  • Typo in Bearer token

Example error response:

{
  "error": "Unauthorized",
  "message": "Unauthenticated.",
  "status": 401
}

How to fix:

// ❌ Bad: Missing Authorization header
fetch('https://versedb.com/api/user/collection')

// ✅ Good: Proper authentication
fetch('https://versedb.com/api/user/collection', {
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN_HERE'
  }
})

Troubleshooting steps:

  1. Verify token exists and is copied correctly
  2. Check for extra spaces or characters in token
  3. Ensure using Bearer prefix (not Token or Basic)
  4. Generate new token at: https://versedb.com/user/api-tokens
  5. Test token with a simple endpoint first (e.g., GET /api/user)

Example: Testing your token

curl -H "Authorization: Bearer YOUR_TOKEN" \
     https://versedb.com/api/user

402 – Payment Required

You're trying to access a PRO-only feature without a PRO subscription.

Common causes:

  • Accessing relationship endpoints (/api/series/{id}/issues)
  • Accessing market data endpoints
  • PRO-only features with free account

Example error response:

{
  "error": "Payment Required",
  "message": "This endpoint requires a PRO subscription.",
  "status": 402
}

How to fix:


403 – Forbidden

You are authenticated but lack permission to perform this action.

Common causes:

  • Token lacks required scope/permission
  • Attempting to access another user's private data
  • Attempting admin operations without admin role
  • Resource privacy settings prevent access

Example error response:

{
  "error": "Forbidden",
  "message": "This action is unauthorized.",
  "status": 403
}

How to fix:

  1. Check token permissions:

  2. Verify resource access:

    • Ensure you're accessing your own data, not someone else's
    • Check if user profile is public if accessing public endpoints

Token abilities:

  • read:public – Read public comic data
  • read:user – Read your personal data
  • write:lists – Manage collections, wishlists, pull lists
  • write:reviews – Write reviews
  • write:favorites – Manage favorites

404 – Not Found

The requested resource doesn't exist.

Common causes:

  • Incorrect or non-existent ID
  • Typo in endpoint path
  • Using slug instead of numeric ID
  • Resource was deleted

Example error response:

{
  "error": "Not Found",
  "message": "No query results for model [Series] 99999",
  "status": 404
}

How to fix:

// ❌ Bad: Using slug
GET /api/series/amazing-spider-man-2018

// ✅ Good: Using numeric ID
GET /api/series/123

// ❌ Bad: Wrong path
GET /api/serie/123  // Typo: "serie" instead of "series"

// ✅ Good: Correct path
GET /api/series/123

Debugging:

  • Verify ID exists by searching first
  • Check endpoint path against API docs
  • Use numeric IDs, not slugs

405 – Method Not Allowed

You're using the wrong HTTP method for this endpoint.

Common causes:

  • Using POST instead of GET
  • Using GET instead of POST
  • Using PUT instead of PATCH (or vice versa)
  • Endpoint doesn't support that method

Example error response:

{
  "error": "Method Not Allowed",
  "message": "The GET method is not supported for this route.",
  "status": 405
}

How to fix:

// ❌ Bad: Using GET for write operation
GET /api/user/collection

// ✅ Good: Use POST to add to collection
POST /api/user/collection

// ❌ Bad: Using POST to fetch data
POST /api/series/123

// ✅ Good: Use GET to read data
GET /api/series/123

HTTP method reference:

  • GET – Read/retrieve data
  • POST – Create new resources
  • PUT/PATCH – Update existing resources
  • DELETE – Remove resources

422 – Unprocessable Entity

Request is well-formed but contains semantic errors or validation failures.

Common causes:

  • Validation rules failed
  • Invalid data values
  • Foreign key constraints violated
  • Business logic rules not met

Example error response:

{
  "error": "Unprocessable Entity",
  "message": "The given data was invalid.",
  "errors": {
    "issue_id": ["The selected issue id is invalid."],
    "condition": ["The condition must be one of: M, NM, VF, F, VG, G, FR, PR"]
  },
  "status": 422
}

How to fix:

  • Read the errors object for specific field issues
  • Validate data before sending
  • Check allowed values for enum fields
  • Ensure foreign keys reference existing records

429 – Too Many Requests

You've exceeded your rate limit.

Example error response:

{
  "error": "Too Many Requests",
  "message": "API rate limit exceeded. Please try again later.",
  "retry_after": 3600,
  "limit": 300,
  "reset_at": "2025-04-12T15:00:00Z",
  "status": 429
}

Response headers:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1712869200
Retry-After: 3600

How to handle:

async function fetchWithRateLimit(url, options) {
  const response = await fetch(url, options);
  
  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
    console.log(`Rate limited. Waiting ${retryAfter}s...`);
    
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    return fetchWithRateLimit(url, options); // Retry
  }
  
  return response;
}

Prevention:

  • Monitor X-RateLimit-Remaining header
  • Implement request throttling in your client
  • Cache frequently accessed data
  • Upgrade to PRO for higher limits (1000/hour vs 300/hour)

500 – Internal Server Error

Something went wrong on the VerseDB server.

Example error response:

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred.",
  "status": 500
}

What to do:

  1. Retry with exponential backoff:
async function retryOnServerError(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url);
    
    if (response.status === 500) {
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
      continue;
    }
    
    return response;
  }
  throw new Error('Server error persists after retries');
}
  1. If error persists:
    • Check VerseDB status page (if available)
    • Report issue to support with request details
    • Include timestamp, endpoint, and request body

Note: 500 errors are usually temporary. If consistent, contact support.


503 – Service Unavailable

The server is temporarily unavailable (maintenance, overload, etc.)

Example error response:

{
  "error": "Service Unavailable",
  "message": "The service is temporarily unavailable.",
  "status": 503
}

What to do:

  • Wait a few minutes and retry
  • Check for scheduled maintenance announcements
  • Implement graceful degradation in your app

Quick Reference Table

Code Error Common Fix
400 Bad Request Check JSON syntax and required fields
401 Unauthorized Add/update Bearer token
402 Payment Required Upgrade to PRO subscription
403 Forbidden Check token permissions/abilities
404 Not Found Verify resource ID exists
405 Method Not Allowed Use correct HTTP method (GET/POST/PUT/DELETE)
422 Unprocessable Entity Fix validation errors in request data
429 Too Many Requests Wait and retry, respect rate limits
500 Server Error Retry with exponential backoff
503 Service Unavailable Wait and retry later

Debugging Tips

Log Full Error Response

fetch(url, {
  headers: { 'Authorization': 'Bearer TOKEN' }
})
  .then(response => {
    if (!response.ok) {
      return response.json().then(error => {
        console.error('API Error:', {
          status: response.status,
          statusText: response.statusText,
          error: error,
          url: url
        });
        throw new Error(error.message || 'API request failed');
      });
    }
    return response.json();
  });

Check Request Headers

Use browser DevTools Network tab or curl with -v flag:

curl -v -H "Authorization: Bearer TOKEN" \
     https://versedb.com/api/user/collection

Test in Isolation

Isolate the failing request and test with minimal data to identify the issue.


For more help: Visit the full API documentation at https://versedb.com/api/docs

Was this article helpful?

Please login to provide feedback