Files
2026-04-17 23:26:01 +00:00

166 lines
4.6 KiB
Markdown

---
title: Handle SDK Errors Properly
impact: HIGH
impactDescription: Graceful error recovery, better UX, easier debugging
tags: sdk, errors, error-handling, exceptions
---
## Handle SDK Errors Properly
All SDK methods return Promises that may reject with `ClientResponseError`. Proper error handling improves user experience and simplifies debugging.
**Incorrect (ignoring or poorly handling errors):**
```javascript
// No error handling
const posts = await pb.collection('posts').getList();
// Generic catch that loses information
try {
await pb.collection('posts').create({ title: '' });
} catch (e) {
alert('Something went wrong'); // No useful info
}
// Not checking specific error types
try {
await pb.collection('posts').getOne('nonexistent');
} catch (e) {
console.log(e.message); // Missing status, response details
}
```
**Correct (comprehensive error handling):**
```javascript
import PocketBase, { ClientResponseError } from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');
// Basic error handling with ClientResponseError
async function createPost(data) {
try {
return await pb.collection('posts').create(data);
} catch (error) {
if (error instanceof ClientResponseError) {
console.log('Status:', error.status);
console.log('Response:', error.response);
console.log('URL:', error.url);
console.log('Is abort:', error.isAbort);
// Handle specific status codes
switch (error.status) {
case 400:
// Validation error - extract user-friendly messages only
// IMPORTANT: Don't expose raw error.response.data to clients
// as it may leak internal field names and validation rules
const fieldErrors = {};
if (error.response?.data) {
for (const [field, details] of Object.entries(error.response.data)) {
fieldErrors[field] = details.message;
}
}
return { error: 'validation', fields: fieldErrors };
case 401:
// Unauthorized - need to login
return { error: 'unauthorized' };
case 403:
// Forbidden - no permission
return { error: 'forbidden' };
case 404:
// Not found
return { error: 'not_found' };
default:
return { error: 'server_error' };
}
}
throw error; // Re-throw non-PocketBase errors
}
}
// Handle validation errors with field details
async function updateProfile(userId, data) {
try {
return await pb.collection('users').update(userId, data);
} catch (error) {
if (error.status === 400 && error.response?.data) {
// Extract field-specific errors
const fieldErrors = {};
for (const [field, details] of Object.entries(error.response.data)) {
fieldErrors[field] = details.message;
}
return { success: false, errors: fieldErrors };
// { errors: { email: "Invalid email format", name: "Required field" } }
}
throw error;
}
}
// Handle request cancellation
async function searchWithCancel(query) {
try {
return await pb.collection('posts').getList(1, 20, {
filter: pb.filter('title ~ {:query}', { query })
});
} catch (error) {
if (error.isAbort) {
// Request was cancelled (e.g., user typed again)
console.log('Search cancelled');
return null;
}
throw error;
}
}
// Wrapper function for consistent error handling
async function pbRequest(fn) {
try {
return { data: await fn(), error: null };
} catch (error) {
if (error instanceof ClientResponseError) {
return {
data: null,
error: {
status: error.status,
message: error.response?.message || 'Request failed',
data: error.response?.data || null
}
};
}
return {
data: null,
error: { status: 0, message: error.message, data: null }
};
}
}
// Usage
const { data, error } = await pbRequest(() =>
pb.collection('posts').getList(1, 20)
);
if (error) {
console.log('Failed:', error.message);
} else {
console.log('Posts:', data.items);
}
```
**ClientResponseError structure:**
```typescript
interface ClientResponseError {
url: string; // The request URL
status: number; // HTTP status code (0 if network error)
response: { // API response body
code: number;
message: string;
data: { [field: string]: { code: string; message: string } };
};
isAbort: boolean; // True if request was cancelled
cause: Error | null; // Original error (added in JS SDK v0.26.1)
}
```
Reference: [PocketBase Error Handling](https://github.com/pocketbase/js-sdk#error-handling)