Skip to main content

Error Response Format

All errors follow a consistent JSON structure:
error
object
required
Error information
meta
object
Response metadata

Example Error Response

curl -X POST "http://localhost:8080/users" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "invalid-email"}'
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "validation failed",
    "details": {
      "email": "invalid email format",
      "name": "field is required"
    }
  },
  "meta": {
    "request_id": "f8a9b0c1d2e3"
  }
}

HTTP Status Codes

Permission Mongo uses standard HTTP status codes:

Success Codes (2xx)

CodeDescriptionUsage
200 OKSuccessGET, PUT, PATCH, DELETE operations
201 CreatedResource createdPOST operations
202 AcceptedRequest acceptedAsync operations
204 No ContentSuccess with no response bodyDELETE operations

Client Error Codes (4xx)

CodeDescriptionError Code
400 Bad RequestInvalid request formatBAD_REQUEST
401 UnauthorizedMissing or invalid authenticationUNAUTHORIZED, INVALID_TOKEN, EXPIRED_TOKEN
403 ForbiddenInsufficient permissionsFORBIDDEN, INVALID_PERMISSION
404 Not FoundResource not foundNOT_FOUND, COLLECTION_NOT_FOUND, DOCUMENT_NOT_FOUND, VERSION_NOT_FOUND
409 ConflictResource conflictCONFLICT, RESOURCE_EXISTS
422 Unprocessable EntityValidation errorVALIDATION_ERROR, SCHEMA_VALIDATION_ERROR
429 Too Many RequestsRate limit exceededRATE_LIMIT_EXCEEDED

Server Error Codes (5xx)

CodeDescriptionError Code
500 Internal Server ErrorServer errorINTERNAL_ERROR
503 Service UnavailableService temporarily unavailableSERVICE_UNAVAILABLE

Error Codes

All error codes defined in the API:

Authentication Errors

UNAUTHORIZED

Status: 401 Unauthorized Cause: Missing or invalid authorization header Example:
curl -X GET "http://localhost:8080/users"
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "missing authorization header"
  },
  "meta": {
    "request_id": "a1b2c3d4e5f6"
  }
}

INVALID_TOKEN

Status: 401 Unauthorized Cause: JWT token is malformed, has invalid signature, or wrong algorithm
{
  "error": {
    "code": "INVALID_TOKEN",
    "message": "invalid token signature"
  },
  "meta": {
    "request_id": "b2c3d4e5f6a7"
  }
}

EXPIRED_TOKEN

Status: 401 Unauthorized Cause: JWT token has expired (past exp claim)
{
  "error": {
    "code": "EXPIRED_TOKEN",
    "message": "token has expired"
  },
  "meta": {
    "request_id": "c3d4e5f6a7b8"
  }
}

Authorization Errors

FORBIDDEN

Status: 403 Forbidden Cause: User doesn’t have permission to perform this action Example:
curl -X DELETE "http://localhost:8080/users/507f1f77bcf86cd799439011" \
  -H "Authorization: Bearer USER_TOKEN"
{
  "error": {
    "code": "FORBIDDEN",
    "message": "insufficient permissions"
  },
  "meta": {
    "request_id": "d4e5f6a7b8c9"
  }
}

INVALID_PERMISSION

Status: 403 Forbidden Cause: Permission check failed (RBAC rules deny access)
{
  "error": {
    "code": "INVALID_PERMISSION",
    "message": "user cannot delete documents in this collection"
  },
  "meta": {
    "request_id": "e5f6a7b8c9d0"
  }
}

Resource Errors

NOT_FOUND

Status: 404 Not Found Cause: Resource doesn’t exist Example:
curl -X GET "http://localhost:8080/users/invalid_id" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "error": {
    "code": "NOT_FOUND",
    "message": "resource not found"
  },
  "meta": {
    "request_id": "f6a7b8c9d0e1"
  }
}

DOCUMENT_NOT_FOUND

Status: 404 Not Found Cause: Specific document doesn’t exist in collection
{
  "error": {
    "code": "DOCUMENT_NOT_FOUND",
    "message": "document not found in collection 'users'"
  },
  "meta": {
    "request_id": "a7b8c9d0e1f2"
  }
}

COLLECTION_NOT_FOUND

Status: 404 Not Found Cause: Collection doesn’t exist or not configured
{
  "error": {
    "code": "COLLECTION_NOT_FOUND",
    "message": "collection 'unknown_collection' not found"
  },
  "meta": {
    "request_id": "b8c9d0e1f2a3"
  }
}

VERSION_NOT_FOUND

Status: 404 Not Found Cause: Document version doesn’t exist
{
  "error": {
    "code": "VERSION_NOT_FOUND",
    "message": "version 5 not found for document"
  },
  "meta": {
    "request_id": "c9d0e1f2a3b4"
  }
}

Validation Errors

BAD_REQUEST

Status: 400 Bad Request Cause: Malformed request (invalid JSON, missing required headers, etc.) Example:
curl -X POST "http://localhost:8080/users" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: text/plain" \
  -d 'not json'
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "content-type must be application/json"
  },
  "meta": {
    "request_id": "d0e1f2a3b4c5"
  }
}

VALIDATION_ERROR

Status: 422 Unprocessable Entity Cause: Request validation failed (schema validation, field constraints, etc.) Example:
curl -X POST "http://localhost:8080/users" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "not-an-email"}'
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "validation failed",
    "details": {
      "email": "invalid email format",
      "name": "field is required",
      "age": "must be greater than 0"
    }
  },
  "meta": {
    "request_id": "e1f2a3b4c5d6"
  }
}

SCHEMA_VALIDATION_ERROR

Status: 422 Unprocessable Entity Cause: Document doesn’t match collection schema
{
  "error": {
    "code": "SCHEMA_VALIDATION_ERROR",
    "message": "document does not match schema",
    "details": {
      "field": "created_at",
      "expected": "date",
      "received": "string"
    }
  },
  "meta": {
    "request_id": "f2a3b4c5d6e7"
  }
}

Conflict Errors

CONFLICT

Status: 409 Conflict Cause: Resource conflict (e.g., concurrent update)
{
  "error": {
    "code": "CONFLICT",
    "message": "resource has been modified"
  },
  "meta": {
    "request_id": "a3b4c5d6e7f8"
  }
}

RESOURCE_EXISTS

Status: 409 Conflict Cause: Resource with unique identifier already exists Example:
curl -X POST "http://localhost:8080/users" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'
{
  "error": {
    "code": "RESOURCE_EXISTS",
    "message": "user with email '[email protected]' already exists"
  },
  "meta": {
    "request_id": "b4c5d6e7f8a9"
  }
}

Rate Limiting Errors

RATE_LIMIT_EXCEEDED

Status: 429 Too Many Requests Cause: Too many requests from client (see Rate Limits)
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "rate limit exceeded, try again later"
  },
  "meta": {
    "request_id": "c5d6e7f8a9b0"
  }
}

Server Errors

INTERNAL_ERROR

Status: 500 Internal Server Error Cause: Unexpected server error
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "internal server error"
  },
  "meta": {
    "request_id": "d6e7f8a9b0c1"
  }
}
When you encounter an INTERNAL_ERROR, use the request_id to search server logs for details.

SERVICE_UNAVAILABLE

Status: 503 Service Unavailable Cause: Service temporarily unavailable (database down, maintenance, etc.)
{
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "service temporarily unavailable"
  },
  "meta": {
    "request_id": "e7f8a9b0c1d2"
  }
}

Error Details

The details field provides additional context for errors:

Validation Error Details

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "validation failed",
    "details": {
      "email": "invalid email format",
      "age": "must be between 0 and 150",
      "roles": "array must contain at least one item"
    }
  }
}

Schema Error Details

{
  "error": {
    "code": "SCHEMA_VALIDATION_ERROR",
    "message": "document does not match schema",
    "details": {
      "field": "metadata.tags",
      "reason": "expected array, got string"
    }
  }
}

Best Practices

  1. Check Status Code: Always check HTTP status code first
  2. Use Error Codes: Parse the error.code field for programmatic handling
  3. Log Request IDs: Save request_id for debugging and support
  4. Handle All Error Types: Implement handlers for all error codes
  5. User-Friendly Messages: Show error.message to users
  6. Retry Logic: Implement exponential backoff for 5xx errors
  7. Validation: Show error.details for validation failures

Example Error Handling

JavaScript/TypeScript

async function fetchUser(userId: string) {
  try {
    const response = await fetch(`http://localhost:8080/users/${userId}`, {
      headers: {
        'Authorization': `Bearer ${token}`,
      },
    });

    if (!response.ok) {
      const errorData = await response.json();
      
      switch (errorData.error.code) {
        case 'UNAUTHORIZED':
        case 'EXPIRED_TOKEN':
          // Redirect to login
          redirectToLogin();
          break;
          
        case 'NOT_FOUND':
        case 'DOCUMENT_NOT_FOUND':
          // Show not found message
          showError('User not found');
          break;
          
        case 'FORBIDDEN':
          // Show permission denied
          showError('You do not have permission to view this user');
          break;
          
        case 'INTERNAL_ERROR':
          // Log and show generic error
          console.error('Request ID:', errorData.meta.request_id);
          showError('An error occurred. Please try again later.');
          break;
          
        default:
          console.error('Unhandled error:', errorData.error.code);
          showError(errorData.error.message);
      }
      
      return null;
    }

    return await response.json();
  } catch (error) {
    console.error('Network error:', error);
    showError('Network error. Please check your connection.');
    return null;
  }
}

Python

import requests

def fetch_user(user_id: str, token: str):
    try:
        response = requests.get(
            f'http://localhost:8080/users/{user_id}',
            headers={'Authorization': f'Bearer {token}'}
        )
        
        if not response.ok:
            error_data = response.json()
            error_code = error_data['error']['code']
            request_id = error_data['meta']['request_id']
            
            if error_code in ['UNAUTHORIZED', 'EXPIRED_TOKEN']:
                # Handle authentication error
                raise AuthenticationError('Please log in again')
            elif error_code in ['NOT_FOUND', 'DOCUMENT_NOT_FOUND']:
                # Handle not found
                raise NotFoundError('User not found')
            elif error_code == 'FORBIDDEN':
                # Handle permission error
                raise PermissionError('Insufficient permissions')
            elif error_code == 'INTERNAL_ERROR':
                # Log and raise
                print(f'Internal error, request_id: {request_id}')
                raise ServerError('Server error occurred')
            else:
                # Handle unknown error
                raise APIError(error_data['error']['message'])
        
        return response.json()
    
    except requests.RequestException as e:
        print(f'Network error: {e}')
        raise NetworkError('Network error occurred')

Debugging

Request ID Tracking

Every error includes a request_id in the meta field. Use this to:
  1. Search server logs
  2. Trace request through distributed systems
  3. Report issues to support
  4. Debug in production

Server Logs

Server logs include structured information:
{
  "timestamp": "2026-03-04T10:15:30Z",
  "level": "error",
  "request_id": "d6e7f8a9b0c1",
  "method": "POST",
  "path": "/users",
  "status": 422,
  "error": "validation failed",
  "details": {
    "email": "invalid email format"
  }
}

Build docs developers (and LLMs) love