Error Handling
Error types and handling patterns for Gatekeeper middleware
Gatekeeper provides typed error classes for consistent error handling across your application.
Error Classes
AuthError
Thrown when authentication fails.
import { AuthError } from '@mira.network/gatekeeper';
// Thrown when:
// - Authorization header is missing
// - Token format is invalid
// - Token prefix doesn't match service
// - API key validation failsHTTP Status: 401 Unauthorized
Response Format:
{
"error": "Unauthorized",
"message": "Authorization header required"
}RateLimitError
Thrown when rate limit is exceeded.
import { RateLimitError } from '@mira.network/gatekeeper';
// Properties:
// - type: 'minute' | 'day' - Which limit was exceeded
// - resetAt: number - Unix timestamp when limit resets
// - retryAfter: number - Seconds until limit resetsHTTP Status: 429 Too Many Requests
Response Format:
{
"error": "Rate Limit Exceeded",
"message": "Per-minute rate limit exceeded",
"resetAt": 1699999999
}Headers:
Retry-After: 45InsufficientBalanceError
Thrown when app has insufficient balance.
import { InsufficientBalanceError } from '@mira.network/gatekeeper';
// Properties:
// - balance: number - Current balanceHTTP Status: 402 Payment Required
Response Format:
{
"error": "Payment Required",
"message": "Insufficient balance",
"balance": 0
}Error Handling Pattern
Handle all Gatekeeper errors in your Hono app's error handler:
import {
AuthError,
RateLimitError,
InsufficientBalanceError,
} from '@mira.network/gatekeeper';
app.onError((err, c) => {
if (err instanceof AuthError) {
return c.json(
{ error: 'Unauthorized', message: err.message },
401
);
}
if (err instanceof RateLimitError) {
c.header('Retry-After', err.retryAfter.toString());
return c.json(
{
error: 'Rate Limit Exceeded',
message: err.message,
resetAt: err.resetAt,
},
429
);
}
if (err instanceof InsufficientBalanceError) {
return c.json(
{
error: 'Payment Required',
message: 'Insufficient balance',
balance: err.balance,
},
402
);
}
// Handle other errors
console.error(err);
return c.json({ error: 'Internal Server Error' }, 500);
});Type Guards
You can also use instanceof checks in try-catch blocks:
app.post('/api/endpoint', async (c) => {
try {
// Your handler logic
} catch (err) {
if (err instanceof AuthError) {
// Handle auth error
}
throw err; // Re-throw to global error handler
}
});Error Properties Reference
| Error Class | Properties |
|---|---|
AuthError | message: string |
RateLimitError | type: 'minute' | 'day', resetAt: number, retryAfter: number |
InsufficientBalanceError | balance: number |