Skip to main content

Overview

The TrackGeek API uses a centralized error handling system that provides consistent, structured error responses across all endpoints. All errors follow a standard format with error codes and HTTP status codes.

Error Response Format

All API errors return a JSON response with the following structure:
{
  "code": "ERROR_CODE",
  "status": 400
}
  • code: A string constant identifying the specific error type
  • status: The HTTP status code associated with the error

HTTP Status Codes

The API uses standard HTTP status codes to indicate the type of error:
Status CodeMeaningUsage
400Bad RequestInvalid request parameters or malformed data
401UnauthorizedMissing or invalid authentication
404Not FoundRequested resource does not exist
409ConflictResource already exists or constraint violation
415Unsupported Media TypeInvalid file type (e.g., image uploads)
422Unprocessable EntityValidation error or invalid entity state
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server error
503Service UnavailableExternal service unavailable

Common Error Codes

Authentication & Authorization

{
  "code": "UNAUTHORIZED",
  "status": 401
}
Returned when authentication is required but not provided or is invalid.

Resource Not Found

{
  "code": "USER_NOT_FOUND",
  "status": 404
}

Conflict Errors

{
  "code": "FAVORITE_ALREADY_EXISTS",
  "status": 409
}
Database conflicts (like unique constraint violations) are automatically mapped to the DATABASE_CONFLICT error code.

Validation Errors

{
  "code": "DATABASE_VALIDATION_ERROR",
  "status": 422
}
Returned when database validation fails or when request data doesn’t meet schema requirements.

Rate Limiting

{
  "code": "RATE_LIMIT_EXCEEDED",
  "status": 429
}
See the Rate Limiting guide for details on rate limits and block durations.

External Service Errors

{
  "code": "GAME_SERVICE_UNAVAILABLE",
  "status": 503
}

Upload Errors

{
  "code": "IMAGE_TYPE_NOT_SUPPORTED",
  "status": 415
}

Database Exception Handling

The API automatically converts Prisma database errors into user-friendly error responses:

Prisma Error Mappings

Prisma Error CodeError ResponseDescription
P2002, P2003DATABASE_CONFLICTUnique constraint or foreign key violation
P2025DATABASE_ITEM_NOT_FOUNDRecord not found in database
Validation ErrorDATABASE_VALIDATION_ERRORInvalid data type or format
These mappings are handled automatically by the HttpExceptionFilter at src/shared/filters/http-exception.filter.ts:14-32.

Handling Errors in Your Application

TypeScript Example

import axios, { AxiosError } from 'axios';

interface TrackGeekError {
  code: string;
  status: number;
}

async function getGame(id: string) {
  try {
    const response = await axios.get(`https://api.trackgeek.com/games/${id}`);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      const trackGeekError = error.response?.data as TrackGeekError;
      
      switch (trackGeekError.code) {
        case 'GAME_NOT_FOUND':
          console.error('Game does not exist');
          break;
        case 'RATE_LIMIT_EXCEEDED':
          console.error('Too many requests, please wait');
          break;
        case 'UNAUTHORIZED':
          console.error('Authentication required');
          break;
        default:
          console.error('An error occurred:', trackGeekError.code);
      }
    }
    throw error;
  }
}

JavaScript Example

async function createReview(gameId, reviewData) {
  try {
    const response = await fetch(`https://api.trackgeek.com/games/${gameId}/reviews`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(reviewData)
    });
    
    if (!response.ok) {
      const error = await response.json();
      
      if (error.code === 'REVIEW_ALREADY_EXISTS') {
        alert('You have already reviewed this game');
        return;
      }
      
      if (error.code === 'RATE_LIMIT_EXCEEDED') {
        alert('Too many requests. Please wait a few minutes.');
        return;
      }
      
      throw new Error(error.code);
    }
    
    return await response.json();
  } catch (error) {
    console.error('Failed to create review:', error);
    throw error;
  }
}

Python Example

import requests
from typing import Dict, Any

def get_user_profile(user_id: str) -> Dict[str, Any]:
    try:
        response = requests.get(f"https://api.trackgeek.com/users/{user_id}/profile")
        response.raise_for_status()
        return response.json()
    except requests.HTTPError as e:
        error_data = e.response.json()
        error_code = error_data.get("code")
        
        if error_code == "PROFILE_NOT_FOUND":
            print("Profile does not exist")
        elif error_code == "UNAUTHORIZED":
            print("Authentication required")
        elif error_code == "RATE_LIMIT_EXCEEDED":
            print("Rate limit exceeded, please wait")
        else:
            print(f"Error: {error_code}")
        
        raise

Complete Error Code Reference

For a complete list of all error codes, see the source at src/shared/constants/error-codes.ts. The main categories include:
  • User & Profile Errors: USER_NOT_FOUND, PROFILE_NOT_FOUND, USER_CANNOT_FOLLOW_SELF, etc.
  • Content Errors: GAME_NOT_FOUND, MOVIE_NOT_FOUND, ANIME_NOT_FOUND, BOOK_NOT_FOUND, etc.
  • Review Errors: REVIEW_NOT_FOUND, REVIEW_ALREADY_EXISTS
  • List Errors: LIST_NOT_FOUND, LIST_ALREADY_EXISTS, LIST_ITEM_NOT_FOUND
  • Favorite Errors: FAVORITE_NOT_FOUND, FAVORITE_ALREADY_EXISTS
  • Database Errors: DATABASE_CONFLICT, DATABASE_ITEM_NOT_FOUND, DATABASE_VALIDATION_ERROR
  • Service Errors: GAME_SERVICE_UNAVAILABLE, TMDB_SERVICE_UNAVAILABLE, etc.
Always handle errors gracefully in production applications. Never expose raw error messages to end users.

Build docs developers (and LLMs) love