Skip to main content

Error Handling

Structured error handling for App Functions with semantic error codes.

FunctionError

Throw FunctionError in your function handlers to return structured error responses:

import { FunctionError } from '@edgebase/shared';

export const POST = defineFunction(async ({ auth, admin }) => {
if (!auth) {
throw new FunctionError('unauthenticated', 'Login required');
}

if (auth.custom?.role !== 'admin') {
throw new FunctionError('permission-denied', 'Admin access required');
}

const user = await admin.db('shared').table('users').get(auth.id);
if (!user) {
throw new FunctionError('not-found', 'User not found');
}

// Check preconditions before proceeding
if (user.status !== 'active') {
throw new FunctionError('failed-precondition', 'Account must be active to perform this action');
// Returns HTTP 412 Precondition Failed
}

return user;
});

Error Codes

CodeHTTP StatusDescription
unauthenticated401No auth token or invalid token
permission-denied403Authenticated but not authorized
not-found404Resource not found
invalid-argument400Bad request parameters
already-exists409Resource already exists
resource-exhausted429Rate limit exceeded
failed-precondition412Operation prerequisites not met
internal500Internal server error
unavailable503Service temporarily unavailable

Error Response Format

When a FunctionError is thrown, the client receives:

{
"code": "permission-denied",
"message": "Admin access required",
"status": 403
}

Error Details

Pass additional context with the details parameter:

throw new FunctionError('invalid-argument', 'Validation failed', {
field: 'email',
reason: 'Invalid email format',
});

Response:

{
"code": "invalid-argument",
"message": "Validation failed",
"status": 400,
"details": { "field": "email", "reason": "Invalid email format" }
}

Client-Side Handling

Errors thrown by functions are caught as EdgeBaseError in the client SDK:

import { EdgeBaseError } from '@edgebase/web';

try {
await client.functions.post('create-order', { items: [] });
} catch (err) {
if (err instanceof EdgeBaseError) {
switch (err.code) {
case 401: // unauthenticated
redirectToLogin();
break;
case 403: // permission-denied
showAccessDenied();
break;
default:
showError(err.message);
}
}
}

Unhandled Errors

If a function throws a non-FunctionError error (e.g., throw new Error(...)), the server returns a generic 500 response. The actual error message is logged server-side but not exposed to the client for security.