Skip to content

Error Handling

Overview

All API endpoints follow a consistent error response format for easy error handling in client applications.

Standard Error Format

json
{
  "success": false,
  "error": "Human-readable error message",
  "code": "ERROR_CODE",
  "details": {}
}

HTTP Status Codes

StatusMeaningWhen Used
200 OKSuccessRequest completed successfully
201 CreatedCreatedResource created successfully
400 Bad RequestClient ErrorInvalid request data
401 UnauthorizedAuth RequiredMissing or invalid token
403 ForbiddenAccess DeniedUser lacks permission
404 Not FoundNot FoundResource doesn't exist
429 Too Many RequestsRate LimitedToo many requests
500 Internal Server ErrorServer ErrorUnexpected server error
502 Bad GatewayExternal ErrorExternal service (Steam) error
503 Service UnavailableUnavailableService temporarily unavailable
504 Gateway TimeoutTimeoutExternal service timeout

Common Error Codes

Authentication Errors

CodeHTTPDescription
UNAUTHORIZED401Missing or invalid authentication token
TOKEN_EXPIRED401JWT token has expired
FORBIDDEN403User doesn't have permission
INVALID_STEAM_ID400Steam ID format is invalid

Example:

json
{
  "success": false,
  "error": "Authentication required",
  "code": "UNAUTHORIZED"
}

Validation Errors

CodeHTTPDescription
VALIDATION_ERROR400Invalid request data
MISSING_PARAM400Required parameter missing
INVALID_PARAM400Parameter value is invalid

Example:

json
{
  "success": false,
  "error": "Missing required parameter: steamId",
  "code": "MISSING_PARAM",
  "details": {
    "field": "steamId",
    "type": "required"
  }
}

Resource Errors

CodeHTTPDescription
NOT_FOUND404Resource not found
LOADOUT_NOT_FOUND404Loadout doesn't exist
ITEM_NOT_FOUND404Item doesn't exist
DUPLICATE409Resource already exists

Example:

json
{
  "success": false,
  "error": "Loadout not found",
  "code": "LOADOUT_NOT_FOUND",
  "details": {
    "loadoutId": 999
  }
}

Server Errors

CodeHTTPDescription
DATABASE_ERROR500Database operation failed
INTERNAL_ERROR500Unexpected server error

Example:

json
{
  "success": false,
  "error": "Database connection failed",
  "code": "DATABASE_ERROR"
}

External Service Errors

CodeHTTPDescription
STEAM_ERROR502Steam API unavailable
GC_TIMEOUT504Steam Game Coordinator timeout
EXTERNAL_ERROR502External service error

Example:

json
{
  "success": false,
  "error": "Steam Game Coordinator timeout",
  "code": "GC_TIMEOUT",
  "details": {
    "timeout_ms": 30000
  }
}

Inspect System Errors

CodeHTTPDescription
INVALID_URL400Invalid inspect URL format
INVALID_ITEM_TYPE400Unknown item type
DECODE_ERROR400Failed to decode masked data

Example:

json
{
  "success": false,
  "error": "Invalid inspect URL format",
  "code": "INVALID_URL",
  "details": {
    "url": "invalid-url-here"
  }
}

Rate Limiting Errors

CodeHTTPDescription
RATE_LIMIT429Too many requests

Example:

json
{
  "success": false,
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT",
  "details": {
    "retryAfter": 60,
    "limit": 100,
    "remaining": 0
  }
}

Error Handling Best Practices

Client-Side Handling

typescript
async function fetchLoadouts(steamId: string) {
  try {
    const response = await fetch(`/api/loadouts?steamId=${steamId}`);
    const data = await response.json();
    
    if (!data.success) {
      switch (data.code) {
        case 'UNAUTHORIZED':
          // Redirect to login
          break;
        case 'NOT_FOUND':
          // Show empty state
          break;
        default:
          // Show generic error
          console.error(data.error);
      }
      return null;
    }
    
    return data.data;
  } catch (error) {
    // Network error
    console.error('Network error:', error);
    return null;
  }
}

Retry Logic

typescript
async function fetchWithRetry(url: string, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url);
      const data = await response.json();
      
      if (data.code === 'RATE_LIMIT') {
        const retryAfter = data.details?.retryAfter || 60;
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }
      
      if (data.code === 'GC_TIMEOUT' && i < retries - 1) {
        await new Promise(resolve => setTimeout(resolve, 2000));
        continue;
      }
      
      return data;
    } catch (error) {
      if (i === retries - 1) throw error;
    }
  }
}

Debugging

Request ID

All responses include an X-Request-ID header for debugging:

http
X-Request-ID: abc123-def456-ghi789

Include this ID when reporting issues.

Response Time

Responses include timing information:

http
X-Response-Time: 45ms

Built with ❤️ by the CS2Inspect community