Error Response Format
All errors follow this standard structure:Copy
{
"status": false,
"error": "error_code",
"message": "Detailed error message"
}
Common Error Codes
| HTTP Status | Error Code | Description | How to Handle |
|---|---|---|---|
| 400 | eksik alan | Missing required field | Check request body |
| 401 | yetkisiz erişim | Invalid/expired token | Refresh access token |
| 403 | URL hatalı | Invalid UUID or unauthorized | Verify resource ID and permissions |
| 404 | sipariş bulunamadı | Order not found | Order may have been deleted |
| 404 | restoran bulunamadı | Restaurant not found | Check restaurant ID |
| 404 | ürün bulunamadı | Food item not found | Check food ID |
| 422 | eksik alan | Malformed request | Validate request format |
| 429 | çok fazla istek | Rate limit exceeded | Wait 30 seconds before retry |
| 500 | Internal server error | Server error | Retry with exponential backoff |
Error Handling Strategy
Implementation Example
Copy
class APIError extends Error {
constructor(status, errorCode, message) {
super(message);
this.status = status;
this.errorCode = errorCode;
this.name = 'APIError';
}
}
async function makeApiCall(endpoint, options = {}) {
try {
const response = await fetch(endpoint, options);
const data = await response.json();
if (!data.status) {
throw new APIError(
response.status,
data.error,
data.message || data.error
);
}
return data.data;
} catch (error) {
// Handle network errors
if (error instanceof TypeError) {
throw new APIError(0, 'network_error', 'Unable to connect to API');
}
throw error;
}
}
async function handleApiCall(apiFunction) {
try {
return await apiFunction();
} catch (error) {
if (error instanceof APIError) {
return handleAPIError(error);
} else {
console.error('Unexpected error:', error);
throw error;
}
}
}
function handleAPIError(error) {
switch (error.status) {
case 401:
return handleAuthError(error);
case 403:
return handleForbiddenError(error);
case 404:
return handleNotFoundError(error);
case 422:
return handleValidationError(error);
case 429:
return handleRateLimitError(error);
case 500:
return handleServerError(error);
default:
return handleGenericError(error);
}
}
Handling Specific Errors
- 401 - Authentication
- 403 - Forbidden
- 404 - Not Found
- 422 - Validation
- 429 - Rate Limit
- 500 - Server Error
Copy
async function handleAuthError(error) {
console.log('Token expired or invalid');
// 1. Try to refresh token
try {
await refreshAccessToken();
// 2. Retry the failed request
return await retryLastRequest();
} catch (refreshError) {
// 3. If refresh fails, redirect to login
redirectToLogin();
throw new Error('Authentication failed');
}
}
async function refreshAccessToken() {
const credentials = getStoredCredentials();
const response = await login(
credentials.appSecret,
credentials.restSecret
);
storeAccessToken(response.access_token);
return response;
}
Copy
function handleForbiddenError(error) {
if (error.errorCode === 'URL hatalı') {
// Invalid UUID or resource ID
console.error('Invalid resource ID');
notifyUser('The requested resource ID is invalid');
// Log for debugging
logError('Invalid UUID', {
endpoint: error.endpoint,
resourceId: error.resourceId
});
} else {
// Insufficient permissions
console.error('Access denied');
notifyUser('You do not have permission to access this resource');
}
}
Copy
function handleNotFoundError(error) {
switch (error.errorCode) {
case 'sipariş bulunamadı':
console.log('Order not found');
notifyUser('Order not found. It may have been canceled.');
break;
case 'restoran bulunamadı':
console.log('Restaurant not found');
notifyUser('Restaurant not found');
break;
case 'ürün bulunamadı':
console.log('Food item not found');
notifyUser('Menu item not found');
break;
default:
notifyUser('The requested resource was not found');
}
}
Copy
function handleValidationError(error) {
console.error('Validation failed:', error.message);
// Extract field name from error message
const fieldMatch = error.message.match(/(\w+) is required/);
const fieldName = fieldMatch ? fieldMatch[1] : 'unknown';
// Highlight error in UI
highlightErrorField(fieldName);
// Show user-friendly message
notifyUser(`Please provide a valid ${fieldName}`);
// Log for debugging
logValidationError({
field: fieldName,
message: error.message,
requestData: error.requestData
});
}
Copy
async function handleRateLimitError(error) {
console.log('Rate limit exceeded');
// Show user message
notifyUser('Too many requests. Please wait 30 seconds.');
// Wait 30 seconds
await sleep(30000);
// Retry automatically
console.log('Retrying request...');
return await retryLastRequest();
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Copy
async function handleServerError(error, attempt = 1) {
const maxRetries = 3;
console.error(`Server error (attempt ${attempt}/${maxRetries})`);
if (attempt >= maxRetries) {
// Give up after max retries
notifyUser('Server error. Please try again later.');
logCriticalError('Server error after max retries', error);
throw error;
}
// Exponential backoff: 1s, 2s, 4s
const delay = 1000 * Math.pow(2, attempt - 1);
console.log(`Waiting ${delay}ms before retry...`);
await sleep(delay);
// Retry
try {
return await retryLastRequest();
} catch (retryError) {
return handleServerError(retryError, attempt + 1);
}
}
Retry Strategy
Copy
class RetryHandler {
constructor(maxRetries = 3) {
this.maxRetries = maxRetries;
this.retryableErrors = [429, 500, 502, 503, 504];
}
async execute(apiFunction, attempt = 1) {
try {
return await apiFunction();
} catch (error) {
// Check if error is retryable
if (!this.shouldRetry(error, attempt)) {
throw error;
}
// Calculate delay with exponential backoff
const delay = this.calculateDelay(error, attempt);
console.log(`Retry attempt ${attempt}/${this.maxRetries} in ${delay}ms`);
await sleep(delay);
// Retry
return this.execute(apiFunction, attempt + 1);
}
}
shouldRetry(error, attempt) {
if (attempt >= this.maxRetries) {
return false;
}
if (error instanceof APIError) {
return this.retryableErrors.includes(error.status);
}
// Retry network errors
return error instanceof TypeError;
}
calculateDelay(error, attempt) {
// Rate limit: wait full 30 seconds
if (error.status === 429) {
return 30000;
}
// Exponential backoff for other errors: 1s, 2s, 4s
return 1000 * Math.pow(2, attempt - 1);
}
}
// Usage
const retryHandler = new RetryHandler(3);
try {
const orders = await retryHandler.execute(() =>
getOrders()
);
} catch (error) {
console.error('Failed after retries:', error);
}
Logging Best Practices
Copy
class ErrorLogger {
log(error, context = {}) {
const logEntry = {
timestamp: new Date().toISOString(),
error: {
name: error.name,
message: error.message,
stack: error.stack,
status: error.status,
errorCode: error.errorCode
},
context: {
...context,
userId: currentUser?.id,
restaurantId: currentRestaurant?.id,
endpoint: context.endpoint,
requestData: context.requestData
},
environment: process.env.NODE_ENV,
version: APP_VERSION
};
// Log to console
console.error('API Error:', logEntry);
// Send to error tracking service
if (errorTracker) {
errorTracker.captureException(error, logEntry);
}
// Store locally for debugging
this.storeLog(logEntry);
}
storeLog(logEntry) {
const logs = JSON.parse(localStorage.getItem('errorLogs') || '[]');
logs.push(logEntry);
// Keep only last 100 errors
if (logs.length > 100) {
logs.shift();
}
localStorage.setItem('errorLogs', JSON.stringify(logs));
}
getLogs() {
return JSON.parse(localStorage.getItem('errorLogs') || '[]');
}
}
const logger = new ErrorLogger();
// Usage
try {
await apiCall();
} catch (error) {
logger.log(error, {
endpoint: '/orders/get-current',
operation: 'fetch_orders'
});
}
User-Friendly Messages
Technical vs User Messages
Technical vs User Messages
Copy
function getUserMessage(error) {
const messages = {
401: 'Your session has expired. Please log in again.',
403: 'You don\'t have permission to perform this action.',
404: 'The requested item was not found.',
422: 'Please check your input and try again.',
429: 'Too many requests. Please wait a moment.',
500: 'Something went wrong. Please try again later.'
};
return messages[error.status] ||
'An unexpected error occurred. Please try again.';
}
Error Notifications
Error Notifications
Copy
function notifyUser(message, type = 'error') {
const notification = {
error: { color: 'red', icon: '❌' },
warning: { color: 'orange', icon: '⚠️' },
info: { color: 'blue', icon: 'ℹ️' }
}[type];
showToast(`${notification.icon} ${message}`, notification.color);
}
Complete Error Handling System
Copy
class APIClient {
constructor() {
this.retryHandler = new RetryHandler(3);
this.logger = new ErrorLogger();
}
async request(endpoint, options = {}) {
return this.retryHandler.execute(async () => {
try {
const response = await fetch(endpoint, {
...options,
headers: {
'Access-Token': await this.getToken(),
'Content-Type': 'application/json',
...options.headers
}
});
const data = await response.json();
if (!data.status) {
throw new APIError(
response.status,
data.error,
data.message
);
}
return data.data;
} catch (error) {
this.logger.log(error, {
endpoint,
method: options.method || 'GET',
requestData: options.body
});
throw error;
}
});
}
async getToken() {
// Token management logic
return tokenManager.getValidToken();
}
}
// Usage
const api = new APIClient();
try {
const orders = await api.request('/orders/get-current');
processOrders(orders);
} catch (error) {
const message = getUserMessage(error);
notifyUser(message);
}
Monitoring & Alerts
Set up monitoring for:- High error rates (> 5%)
- Repeated 401 errors (auth issues)
- Frequent 429 errors (rate limiting)
- 500 errors (server issues)
- Network timeouts
Copy
class ErrorMonitor {
constructor() {
this.errorCounts = {};
this.alertThresholds = {
401: 3, // Alert after 3 auth errors
429: 5, // Alert after 5 rate limits
500: 2 // Alert after 2 server errors
};
}
recordError(error) {
const code = error.status;
this.errorCounts[code] = (this.errorCounts[code] || 0) + 1;
if (this.shouldAlert(code)) {
this.sendAlert(code, this.errorCounts[code]);
}
}
shouldAlert(code) {
const threshold = this.alertThresholds[code] || 10;
return this.errorCounts[code] >= threshold;
}
sendAlert(code, count) {
console.error(`🚨 ALERT: ${count} errors with code ${code}`);
// Send to monitoring service
}
}
Need Help?
Having persistent errors? Contact our support team for assistance.