Files
formbricks/docs/development/standards/practices/error-handling.mdx
Dhruwang Jariwala ee2573d128 docs: coding standards (#4770)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Matti Nannt <mail@matthiasnannt.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-02-19 18:45:13 +01:00

137 lines
3.4 KiB
Plaintext

---
title: "Error Handling"
description: "Standards for handling errors across the Formbricks codebase"
icon: "triangle-exclamation"
---
## Overview
At Formbricks, we follow consistent error handling patterns to ensure reliability, debuggability, and maintainability across our codebase. This document outlines our standard approaches to error handling.
## Core Principles
1. **Type Safety**: Use typed errors and results
2. **Meaningful Messages**: Provide clear, actionable error messages
3. **Proper Propagation**: Handle or propagate errors appropriately
4. **Logging**: Ensure errors are properly logged for debugging
5. **Recovery**: Implement graceful fallbacks where possible
## Standard Error Types
We maintain a set of standardized error types for different scenarios:
```typescript
export interface ApiErrorResponse {
code:
| "not_found"
| "gone"
| "bad_request"
| "internal_server_error"
| "unauthorized"
| "method_not_allowed"
| "not_authenticated"
| "forbidden"
| "network_error";
message: string;
status: number;
url: URL;
details?: Record<string, string | string[] | number | number[] | boolean | boolean[]>;
responseMessage?: string;
}
```
## Error Handling Patterns
### API Error Handling
For API endpoints:
```typescript
export const GET = async (request: Request) => {
try {
const authentication = await authenticateRequest(request);
if (!authentication) return responses.notAuthenticatedResponse();
const data = await fetchData(authentication.environmentId!);
return responses.successResponse(data);
} catch (error) {
if (error instanceof DatabaseError) {
return responses.badRequestResponse(error.message);
}
throw error;
}
};
```
### Client-Side Error Handling
For client-side operations:
```typescript
const handleOperation = async () => {
const result = await performAction();
if (!result.ok) {
logger.error(`Operation failed: ${result.error.message}`);
toast.error("Operation failed. Please try again.");
return;
}
// Process successful result
processResult(result.data);
};
```
## Best Practices
1. **Never Swallow Errors**
- Always handle or propagate errors
- Log errors appropriately for debugging
- Use error boundaries in React components
2. **Type Safety**
- Use typed error responses
- Leverage TypeScript for compile-time error checking
- Define clear error interfaces
3. **Error Messages**
- Include relevant context in error messages
- Make messages actionable for developers
- Use consistent error formatting
4. **Error Recovery**
- Implement fallback behaviors where appropriate
- Gracefully degrade functionality when possible
- Provide user feedback for recoverable errors
5. **Documentation**
- Document expected errors in function JSDoc
- Include error handling in code examples
- Keep error handling documentation up to date
## Testing Error Scenarios
Always include error case testing:
```typescript
describe("fetchEnvironmentState()", () => {
test("returns err(...) on network error", async () => {
const mockNetworkError = {
code: "network_error",
message: "Timeout",
responseMessage: "Network fail",
};
const result = await fetchEnvironmentState();
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error.code).toBe(mockNetworkError.code);
expect(result.error.message).toBe(mockNetworkError.message);
}
});
});
```
These standards ensure consistent, reliable error handling across the Formbricks codebase while maintaining good developer experience and system reliability.