Errors
Error Handling
Section titled “Error Handling”The BitMarks API uses standard HTTP status codes and returns consistent error responses.
Error Response Format
Section titled “Error Response Format”All errors return a JSON object with an error field:
{ "error": "Human-readable error message"}In development mode, additional debugging information may be included:
{ "error": "Something went wrong", "details": "Additional context", "stack": "Error: Something went wrong\n at ..."}HTTP Status Codes
Section titled “HTTP Status Codes”Success Codes
Section titled “Success Codes”| Code | Name | Description |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully |
302 | Found | Redirect (OAuth callbacks) |
Client Error Codes
Section titled “Client Error Codes”| Code | Name | Description |
|---|---|---|
400 | Bad Request | Invalid request body or parameters |
401 | Unauthorized | Authentication required or invalid |
403 | Forbidden | Access denied to resource |
404 | Not Found | Resource does not exist |
409 | Conflict | Resource conflict (e.g., duplicate) |
422 | Unprocessable Entity | Valid syntax but semantic errors |
426 | Upgrade Required | WebSocket upgrade expected |
429 | Too Many Requests | Rate limit exceeded |
Server Error Codes
Section titled “Server Error Codes”| Code | Name | Description |
|---|---|---|
500 | Internal Server Error | Unexpected server error |
501 | Not Implemented | Feature not yet available |
503 | Service Unavailable | Temporary service outage |
Common Errors
Section titled “Common Errors”Authentication Errors
Section titled “Authentication Errors”No session cookie:
{ "error": "Authentication required"}Invalid or expired session:
{ "error": "Invalid or expired session"}No refresh token:
{ "error": "No refresh token"}Refresh failed:
{ "error": "Failed to refresh token"}Validation Errors
Section titled “Validation Errors”Invalid request body:
{ "error": "Invalid request body"}Invalid sync changes:
{ "error": "Invalid changes format"}Resource Errors
Section titled “Resource Errors”Bookmark not found:
{ "error": "Bookmark not found"}Export not found:
{ "error": "Export not found"}API endpoint not found:
{ "error": "Not Found", "path": "/api/v1/unknown"}Implementation Errors
Section titled “Implementation Errors”Feature not implemented:
{ "error": "Not implemented"}Server Errors
Section titled “Server Errors”Generic server error:
{ "error": "Internal Server Error"}Login initiation failed:
{ "error": "Failed to initiate login"}Logout failed:
{ "error": "Failed to logout"}Sync status failed:
{ "error": "Failed to get sync status", "details": "Database connection failed"}Error Handling Best Practices
Section titled “Error Handling Best Practices”Client-Side Error Handling
Section titled “Client-Side Error Handling”async function apiRequest<T>(url: string, options?: RequestInit): Promise<T> { const response = await fetch(url, { ...options, credentials: 'include', headers: { 'Content-Type': 'application/json', ...options?.headers, }, });
if (!response.ok) { const error = await response.json();
switch (response.status) { case 401: // Try to refresh token const refreshed = await refreshToken(); if (refreshed) { // Retry request return apiRequest(url, options); } // Redirect to login window.location.href = '/login'; throw new Error('Session expired');
case 429: // Rate limited - wait and retry const retryAfter = response.headers.get('Retry-After') || '60'; await delay(parseInt(retryAfter) * 1000); return apiRequest(url, options);
case 404: throw new NotFoundError(error.error);
case 400: throw new ValidationError(error.error);
default: throw new APIError(error.error, response.status); } }
return response.json();}Custom Error Classes
Section titled “Custom Error Classes”class APIError extends Error { constructor( message: string, public status: number ) { super(message); this.name = 'APIError'; }}
class NotFoundError extends APIError { constructor(message: string) { super(message, 404); this.name = 'NotFoundError'; }}
class ValidationError extends APIError { constructor(message: string) { super(message, 400); this.name = 'ValidationError'; }}
class AuthenticationError extends APIError { constructor(message: string) { super(message, 401); this.name = 'AuthenticationError'; }}React Error Boundary
Section titled “React Error Boundary”import { Component, ErrorInfo, ReactNode } from 'react';
interface Props { children: ReactNode; fallback?: ReactNode;}
interface State { hasError: boolean; error?: Error;}
class APIErrorBoundary extends Component<Props, State> { state: State = { hasError: false };
static getDerivedStateFromError(error: Error): State { return { hasError: true, error }; }
componentDidCatch(error: Error, info: ErrorInfo) { console.error('API Error:', error, info); }
render() { if (this.state.hasError) { return this.props.fallback || ( <div> <h2>Something went wrong</h2> <p>{this.state.error?.message}</p> <button onClick={() => this.setState({ hasError: false })}> Try again </button> </div> ); }
return this.props.children; }}Debugging Tips
Section titled “Debugging Tips”Check Response Headers
Section titled “Check Response Headers”curl -i https://app.bitmarks.sh/api/v1/bookmarks \ -b "bitmarks_session=YOUR_TOKEN"Verify Authentication
Section titled “Verify Authentication”# Check if session is validcurl https://app.bitmarks.sh/api/v1/auth/session \ -b "bitmarks_session=YOUR_TOKEN"Test Health Endpoint
Section titled “Test Health Endpoint”# Verify API is reachablecurl https://app.bitmarks.sh/api/v1/healthReporting Errors
Section titled “Reporting Errors”If you encounter unexpected errors, please report them with:
- Endpoint - The API path called
- Method - GET, POST, PUT, DELETE
- Request body - (without sensitive data)
- Response - The error response received
- Timestamp - When the error occurred