📋 Overview

The NVLP API uses standard HTTP status codes and provides detailed error messages to help you identify and resolve issues quickly. This reference covers all possible error scenarios you might encounter.

🔍 Error Response Format

All error responses follow a consistent JSON format:

{
  "error": "Brief error description",
  "details": "Detailed explanation (optional)",
  "code": "NVLP_ERROR_CODE (optional)",
  "field": "field_name (for validation errors)"
}

🚦 HTTP Status Codes

NVLP API uses standard HTTP status codes to indicate the success or failure of requests:

Status Code Meaning When It Occurs
200 OK Request succeeded
201 Created Resource created successfully
204 No Content Request succeeded, no response body
400 Bad Request Invalid request format or missing required fields
401 Unauthorized Missing, invalid, or expired authentication token
403 Forbidden Valid authentication but insufficient permissions
404 Not Found Resource doesn't exist or user doesn't have access
409 Conflict Request conflicts with current resource state
422 Unprocessable Entity Valid request format but business logic validation failed
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Unexpected server error

🔐 Authentication Errors

Error Status Description Solution
MISSING_AUTH_HEADER 401 No Authorization header provided Include Authorization: Bearer TOKEN header
INVALID_TOKEN_FORMAT 401 Authorization header format is incorrect Use format: Authorization: Bearer YOUR_TOKEN
TOKEN_EXPIRED 401 JWT token has expired Request new magic link or refresh token
INVALID_TOKEN 401 Token signature is invalid or corrupted Request new magic link authentication
USER_NOT_FOUND 401 User associated with token doesn't exist Re-authenticate with magic link
MAGIC_LINK_EXPIRED 400 Magic link has expired (typically after 1 hour) Request a new magic link
MAGIC_LINK_USED 400 Magic link has already been used Request a new magic link
RATE_LIMIT_MAGIC_LINK 429 Too many magic link requests for this email Wait before requesting another magic link

🔧 Quick Fix for Auth Errors

// Check token expiration
function isTokenExpired(token) {
  try {
    const payload = JSON.parse(atob(token.split('.')[1]));
    const currentTime = Math.floor(Date.now() / 1000);
    return payload.exp < currentTime;
  } catch {
    return true;
  }
}

// Handle 401 responses
if (response.status === 401) {
  localStorage.removeItem('nvlp_access_token');
  window.location.href = '/login';
}

✅ Validation Errors

These errors occur when request data doesn't meet the API's validation requirements:

Error Status Description Example
REQUIRED_FIELD_MISSING 400 Required field is missing from request {"error": "Name is required", "field": "name"}
INVALID_EMAIL_FORMAT 400 Email address format is invalid {"error": "Invalid email format", "field": "email"}
INVALID_AMOUNT 400 Amount must be positive number {"error": "Amount must be greater than 0", "field": "amount"}
INVALID_DATE_FORMAT 400 Date format is invalid {"error": "Date must be YYYY-MM-DD format", "field": "transaction_date"}
INVALID_UUID 400 UUID format is invalid {"error": "Invalid UUID format", "field": "budget_id"}
STRING_TOO_LONG 400 String exceeds maximum length {"error": "Name too long (max 255 chars)", "field": "name"}
INVALID_ENUM_VALUE 400 Value not in allowed enum options {"error": "Invalid transaction type", "field": "transaction_type"}

💼 Business Logic Errors

These errors occur when requests are valid but violate business rules:

Error Status Description Solution
INSUFFICIENT_BALANCE 422 Envelope doesn't have enough balance for transaction Check envelope balance or allocate more funds
INVALID_TRANSACTION_FIELDS 422 Transaction type and required fields don't match Review transaction type requirements
CANNOT_DELETE_WITH_BALANCE 409 Cannot delete envelope with non-zero balance Transfer funds out or zero the balance first
CANNOT_TRANSFER_SAME_ENVELOPE 422 Cannot transfer from envelope to itself Choose different source and destination envelopes
BUDGET_ACCESS_DENIED 403 User doesn't have access to this budget Verify budget ownership or permissions
RESOURCE_NOT_FOUND 404 Referenced resource doesn't exist Verify resource ID exists and user has access
DUPLICATE_NAME 409 Resource name already exists in budget Choose a different name
CANNOT_RESTORE_TRANSACTION 409 Transaction cannot be restored due to balance constraints Ensure sufficient balance for restoration

⚠️ Transaction Validation Rules

Different transaction types require specific fields:

  • INCOME: Requires income_source_id only
  • ALLOCATION: Requires to_envelope_id only
  • EXPENSE/DEBT_PAYMENT: Requires from_envelope_id + payee_id
  • TRANSFER: Requires from_envelope_id + to_envelope_id (different)

🚦 Rate Limiting

NVLP implements rate limiting to ensure fair usage and prevent abuse:

Endpoint Limit Window Error Response
Magic Link Requests 5 requests 1 hour {"error": "Too many magic link requests"}
General API 1000 requests 1 hour {"error": "Rate limit exceeded"}
Transaction Creation 100 requests 1 minute {"error": "Too many transactions per minute"}

📊 Rate Limit Headers

Check these response headers to monitor your usage:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200

🔥 Server Errors

Error Status Description Action
INTERNAL_SERVER_ERROR 500 Unexpected server error Retry request, contact support if persistent
DATABASE_ERROR 500 Database connection or query error Retry after a few seconds
SERVICE_UNAVAILABLE 500 Service temporarily unavailable Check status page, retry with exponential backoff

🚨 Server Error Best Practices

  • Implement exponential backoff for retries
  • Don't retry immediately on 5xx errors
  • Log errors for debugging
  • Check our status page for known issues

🔧 Troubleshooting Guide

Common Debugging Steps

🔍 Step-by-Step Debugging

  1. Check HTTP Status Code - Determines error category
  2. Read Error Message - Specific issue description
  3. Verify Request Format - Headers, body, URL parameters
  4. Check Authentication - Token validity and format
  5. Validate Permissions - User access to resources
  6. Review Business Rules - Data constraints and validations

Error Handling Code Examples

// JavaScript error handling
async function handleApiResponse(response) {
  if (!response.ok) {
    const errorData = await response.json();
    
    switch (response.status) {
      case 400:
        console.error('Validation error:', errorData.error);
        if (errorData.field) {
          highlightField(errorData.field);
        }
        break;
        
      case 401:
        console.error('Authentication error');
        redirectToLogin();
        break;
        
      case 403:
        console.error('Permission denied');
        showPermissionError();
        break;
        
      case 422:
        console.error('Business logic error:', errorData.error);
        showBusinessError(errorData.error);
        break;
        
      case 429:
        console.error('Rate limited');
        const retryAfter = response.headers.get('Retry-After');
        scheduleRetry(retryAfter);
        break;
        
      case 500:
        console.error('Server error');
        showRetryOption();
        break;
        
      default:
        console.error('Unknown error:', response.status);
    }
    
    throw new Error(errorData.error);
  }
  
  return response.json();
}

Testing Error Scenarios

Use these cURL commands to test different error conditions:

# Test authentication error (no token)
curl -X GET "https://your-project.supabase.co/rest/v1/budgets"

# Test validation error (invalid email)
curl -X POST "https://your-project.supabase.co/functions/v1/auth-magic-link" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ANON_KEY" \
  -d '{"email": "invalid-email"}'

# Test business logic error (insufficient balance)
curl -X POST "https://your-project.supabase.co/functions/v1/transactions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "budget_id": "your-budget-id",
    "transaction_type": "expense",
    "amount": 9999999,
    "from_envelope_id": "envelope-id",
    "payee_id": "payee-id"
  }'

Getting Help

📞 Support Resources