Skip to main content

Overview

The Masar Eagle API uses standard HTTP status codes and structured error responses to communicate errors. All services implement consistent error handling through the GlobalExceptionMiddleware.

Error Response Format

All error responses follow the RFC 7807 Problem Details specification:
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Invalid request data",
  "status": 400,
  "detail": "Phone number is required and cannot be null",
  "instance": "/api/auth/send-otp",
  "errorId": "A1B2C3D4E5F6",
  "timestamp": "2024-03-10T14:30:00.000Z"
}

Response Fields

type
string
URI reference identifying the error type (RFC 7807 compliant)
title
string
Short, human-readable summary of the error
status
number
HTTP status code
detail
string
Detailed explanation of the error (may include Arabic messages)
instance
string
URI reference to the specific request that caused the error
errorId
string
Unique error identifier for tracking and support (16 character alphanumeric)
timestamp
string
ISO 8601 timestamp when the error occurred
extensions
object
Additional error-specific metadata (development mode only)

HTTP Status Codes

The API uses standard HTTP status codes:

2xx Success

CodeMeaningDescription
200OKRequest succeeded, response body contains data
201CreatedResource successfully created
204No ContentRequest succeeded, no response body

4xx Client Errors

CodeMeaningDescription
400Bad RequestInvalid request data, validation error, or malformed JSON
401UnauthorizedAuthentication required or token invalid/expired
403ForbiddenAuthenticated but insufficient permissions
404Not FoundResource not found
409ConflictResource conflict (e.g., duplicate phone number)

5xx Server Errors

CodeMeaningDescription
500Internal Server ErrorUnexpected server error
501Not ImplementedFeature not yet implemented
502Bad GatewayError connecting to backend service
504Gateway TimeoutRequest timeout

Error Categories

Errors are categorized for easier handling and monitoring:

Validation Errors

Category: ValidationErrorStatus: 400Cause: Invalid input, missing required fields, format errors

Authentication Errors

Category: AuthenticationErrorStatus: 401Cause: Invalid credentials, expired token, missing authentication

Authorization Errors

Category: AuthorizationErrorStatus: 403Cause: Insufficient permissions for the requested operation

Not Found Errors

Category: NotFoundErrorStatus: 404Cause: Requested resource doesn’t exist

Business Logic Errors

Category: BusinessLogicErrorStatus: 400Cause: Operation violates business rules

External Service Errors

Category: ExternalServiceErrorStatus: 502Cause: Failure communicating with external services

Common Error Responses

Validation Errors (400)

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Required data missing",
  "status": 400,
  "detail": "Parameter 'phoneNumber' is required and cannot be null",
  "instance": "/api/auth/send-otp",
  "errorId": "A1B2C3D4E5F6",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Invalid request data",
  "status": 400,
  "detail": "رقم الهاتف يجب أن يكون بصيغة صحيحة",
  "instance": "/api/auth/send-otp",
  "errorId": "B2C3D4E5F6G7",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
{
  "status": 400,
  "title": "Validation failed",
  "errors": [
    {
      "field": "phoneNumber",
      "message": "Phone number must be in E.164 format",
      "code": "VAL_INVALID_PHONE"
    },
    {
      "field": "email",
      "message": "Email address is invalid",
      "code": "VAL_INVALID_EMAIL"
    }
  ]
}

Authentication Errors (401)

{
  "type": "https://tools.ietf.org/html/rfc7235#section-3.1",
  "title": "Unauthorized access",
  "status": 401,
  "detail": "You need to be authenticated to access this resource",
  "instance": "/api/drivers/me",
  "errorId": "C3D4E5F6G7H8",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
{
  "type": "https://tools.ietf.org/html/rfc7235#section-3.1",
  "title": "User not found",
  "status": 401,
  "detail": "The authentication token is invalid or has been revoked",
  "instance": "/api/drivers/me",
  "errorId": "D4E5F6G7H8I9",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
{
  "type": "https://tools.ietf.org/html/rfc7235#section-3.1",
  "title": "User not found",
  "status": 401,
  "detail": "Your session has expired. Please log in again.",
  "instance": "/api/drivers/me",
  "errorId": "E5F6G7H8I9J0",
  "timestamp": "2024-03-10T14:30:00.000Z"
}

Authorization Errors (403)

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.3",
  "title": "User not authorized",
  "status": 403,
  "detail": "You do not have permission to access this resource",
  "instance": "/api/admin/drivers",
  "errorId": "F6G7H8I9J0K1",
  "timestamp": "2024-03-10T14:30:00.000Z"
}

Not Found Errors (404)

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  "title": "Resource not found",
  "status": 404,
  "detail": "The requested resource was not found",
  "instance": "/api/drivers/123e4567-e89b-12d3-a456-426614174000",
  "errorId": "G7H8I9J0K1L2",
  "timestamp": "2024-03-10T14:30:00.000Z"
}

Server Errors (5xx)

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
  "title": "An unexpected error occurred",
  "status": 500,
  "detail": "Please try again later or contact support",
  "instance": "/api/trips",
  "errorId": "H8I9J0K1L2M3",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
Development Mode Response (includes stack trace):
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
  "title": "An unexpected error occurred",
  "status": 500,
  "detail": "Object reference not set to an instance of an object",
  "instance": "/api/trips",
  "errorId": "H8I9J0K1L2M3",
  "timestamp": "2024-03-10T14:30:00.000Z",
  "exceptionType": "System.NullReferenceException",
  "stackTrace": "   at TripService.GetTrip(Guid id) in /src/TripService.cs:line 42\n...",
  "source": "Trips.Api"
}
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.6.3",
  "title": "Service connection error",
  "status": 502,
  "detail": "An error occurred while connecting to an external service",
  "instance": "/api/trips",
  "errorId": "I9J0K1L2M3N4",
  "timestamp": "2024-03-10T14:30:00.000Z"
}
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.6.5",
  "title": "Request timeout",
  "status": 504,
  "detail": "The request took longer than expected",
  "instance": "/api/trips",
  "errorId": "J0K1L2M3N4O5",
  "timestamp": "2024-03-10T14:30:00.000Z"
}

Error Codes Reference

Some services return structured error codes in addition to HTTP status codes:

Authentication Error Codes

CodeDescription
AUTH_INVALID_CREDENTIALSInvalid email or password
AUTH_INVALID_TOKENToken is malformed or invalid
AUTH_TOKEN_EXPIREDToken has expired
AUTH_UNAUTHORIZEDUser is not authorized
AUTH_USER_NOT_FOUNDUser account not found
AUTH_PHONE_NOT_REGISTEREDPhone number not registered

OTP Error Codes

CodeDescription
OTP_INVALIDOTP code is incorrect
OTP_EXPIREDOTP code has expired (5 minutes)
OTP_SEND_FAILEDFailed to send SMS
OTP_TOO_MANY_ATTEMPTSExceeded maximum verification attempts (5)
OTP_NO_CODE_TO_RESENDNo active OTP to resend

Validation Error Codes

CodeDescription
VAL_VALIDATION_FAILEDGeneral validation failure
VAL_INVALID_EMAILEmail format is invalid
VAL_INVALID_PHONEPhone number format is invalid
VAL_INVALID_PASSWORDPassword doesn’t meet requirements
VAL_INVALID_JSONRequest body is not valid JSON

Resource Error Codes

CodeDescription
NF_USER_NOT_FOUNDUser not found
NF_PASSENGER_NOT_FOUNDPassenger not found
NF_DRIVER_NOT_FOUNDDriver not found
NF_VEHICLE_NOT_FOUNDVehicle not found
NF_RESOURCE_NOT_FOUNDGeneric resource not found

Duplicate Error Codes

CodeDescription
DUP_EMAIL_EXISTSEmail already registered
DUP_PHONE_EXISTSPhone number already registered
DUP_VEHICLE_NAME_EXISTSVehicle name already exists

Error Handling Best Practices

1. Handle Errors by Status Code

async function handleAPIRequest(url, options) {
  try {
    const response = await fetch(url, options);
    
    if (!response.ok) {
      const error = await response.json();
      
      switch (response.status) {
        case 400:
          // Validation error - show to user
          showValidationError(error.detail);
          break;
          
        case 401:
          // Unauthorized - refresh token or redirect to login
          await refreshToken();
          break;
          
        case 403:
          // Forbidden - show permission error
          showPermissionError();
          break;
          
        case 404:
          // Not found - show not found message
          showNotFoundError();
          break;
          
        case 429:
          // Rate limited - retry after delay
          const retryAfter = response.headers.get('Retry-After') || 60;
          await sleep(retryAfter * 1000);
          return handleAPIRequest(url, options);
          
        case 500:
        case 502:
        case 503:
        case 504:
          // Server error - log error ID and show generic message
          console.error(`Server error ${error.errorId}`);
          showServerError(error.errorId);
          break;
          
        default:
          // Unknown error
          showGenericError();
      }
      
      throw new Error(error.detail);
    }
    
    return response.json();
  } catch (error) {
    // Network error or parsing error
    console.error('Request failed:', error);
    showNetworkError();
    throw error;
  }
}

2. Log Error IDs for Support

Always log the errorId for 5xx errors to help with troubleshooting:
function logError(error) {
  if (error.status >= 500 && error.errorId) {
    // Send to logging service
    analytics.track('API Error', {
      errorId: error.errorId,
      status: error.status,
      endpoint: error.instance,
      timestamp: error.timestamp,
      userId: getCurrentUserId()
    });
    
    // Show error ID to user for support
    console.error(`Error ID: ${error.errorId}`);
  }
}

3. Handle Authentication Errors

Automatically refresh tokens or redirect to login:
class APIClient {
  async request(url, options) {
    const response = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        'Authorization': `Bearer ${this.accessToken}`
      }
    });
    
    if (response.status === 401) {
      // Try refreshing the token
      const refreshed = await this.refreshToken();
      
      if (refreshed) {
        // Retry with new token
        return this.request(url, options);
      } else {
        // Refresh failed - redirect to login
        window.location.href = '/login';
        throw new Error('Session expired');
      }
    }
    
    return response;
  }
}

4. Display User-Friendly Messages

Translate error messages for users:
const errorMessages = {
  'ar': {
    'AUTH_INVALID_CREDENTIALS': 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
    'OTP_EXPIRED': 'انتهت صلاحية رمز التحقق. يرجى طلب رمز جديد',
    'NF_DRIVER_NOT_FOUND': 'لم يتم العثور على السائق',
    'SERVER_ERROR': 'حدث خطأ في الخادم. يرجى المحاولة مرة أخرى'
  },
  'en': {
    'AUTH_INVALID_CREDENTIALS': 'Invalid email or password',
    'OTP_EXPIRED': 'OTP code has expired. Please request a new one',
    'NF_DRIVER_NOT_FOUND': 'Driver not found',
    'SERVER_ERROR': 'A server error occurred. Please try again'
  }
};

function showError(errorCode, language = 'ar') {
  const message = errorMessages[language][errorCode] 
    || errorMessages[language]['SERVER_ERROR'];
  
  // Show to user
  alert(message);
}

5. Implement Retry Logic

Retry failed requests with exponential backoff:
async function requestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      // Don't retry on client errors (except 429)
      if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        return response;
      }
      
      // Retry on 5xx or 429
      if (response.status >= 500 || response.status === 429) {
        if (attempt < maxRetries - 1) {
          const delay = Math.pow(2, attempt) * 1000;
          console.log(`Retrying after ${delay}ms...`);
          await sleep(delay);
          continue;
        }
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      
      const delay = Math.pow(2, attempt) * 1000;
      await sleep(delay);
    }
  }
}

Error Monitoring

All errors are automatically logged with the following information:
  • Error ID: Unique identifier for tracking
  • Exception Type: Type of exception thrown
  • Request Path: Endpoint that caused the error
  • User ID: Authenticated user (if available)
  • Trace ID: Request trace identifier
  • Stack Trace: Full stack trace (development only)
  • Duration: Time taken before error occurred
For production support, always provide the Error ID when reporting issues. This allows the support team to quickly locate the error in logs.

Next Steps

API Overview

Learn about API structure and conventions

Authentication

Understand authentication flows

Build docs developers (and LLMs) love