0
# Error Handling
1
2
Comprehensive error handling with specific error types and codes for different failure scenarios.
3
4
## Capabilities
5
6
### Error Types
7
8
The Notion SDK provides specific error classes for different types of failures.
9
10
```typescript { .api }
11
/**
12
* Union type of all possible errors from the Notion client
13
*/
14
type NotionClientError =
15
| APIResponseError
16
| UnknownHTTPResponseError
17
| RequestTimeoutError;
18
19
/**
20
* Check if an error is a Notion client error
21
* @param error - Error to check
22
* @returns True if error is from Notion client
23
*/
24
function isNotionClientError(error: unknown): error is NotionClientError;
25
```
26
27
### API Response Errors
28
29
Errors returned from the Notion API with specific error codes.
30
31
```typescript { .api }
32
/**
33
* Error thrown when API returns an error response
34
*/
35
class APIResponseError extends Error {
36
/** Error code from the API */
37
code: APIErrorCode;
38
/** HTTP status code */
39
status: number;
40
/** Additional error details */
41
headers: Record<string, string>;
42
/** Raw response body */
43
body: string;
44
}
45
46
/**
47
* Error codes returned by the Notion API
48
*/
49
enum APIErrorCode {
50
Unauthorized = "unauthorized";
51
RestrictedResource = "restricted_resource";
52
ObjectNotFound = "object_not_found";
53
RateLimited = "rate_limited";
54
InvalidJSON = "invalid_json";
55
InvalidRequestURL = "invalid_request_url";
56
InvalidRequest = "invalid_request";
57
ValidationError = "validation_error";
58
ConflictError = "conflict_error";
59
InternalServerError = "internal_server_error";
60
ServiceUnavailable = "service_unavailable";
61
}
62
```
63
64
**Usage Examples:**
65
66
```typescript
67
import { Client, APIErrorCode, isNotionClientError } from "@notionhq/client";
68
69
const notion = new Client({ auth: process.env.NOTION_TOKEN });
70
71
try {
72
const page = await notion.pages.retrieve({
73
page_id: "invalid-page-id",
74
});
75
} catch (error) {
76
if (isNotionClientError(error)) {
77
console.log(`Notion error: ${error.code}`);
78
79
if (error.code === APIErrorCode.ObjectNotFound) {
80
console.log("Page not found");
81
} else if (error.code === APIErrorCode.Unauthorized) {
82
console.log("Invalid token or insufficient permissions");
83
} else if (error.code === APIErrorCode.RateLimited) {
84
console.log("Rate limited - retry after delay");
85
}
86
} else {
87
console.log("Unknown error:", error);
88
}
89
}
90
```
91
92
### Client Errors
93
94
Errors generated by the client itself, not the API.
95
96
```typescript { .api }
97
/**
98
* Error codes for client-side errors
99
*/
100
enum ClientErrorCode {
101
RequestTimeout = "notionhq_client_request_timeout";
102
ResponseError = "notionhq_client_response_error";
103
}
104
105
/**
106
* Error thrown when request times out
107
*/
108
class RequestTimeoutError extends Error {
109
code: ClientErrorCode.RequestTimeout;
110
}
111
112
/**
113
* Error thrown for unknown HTTP response errors
114
*/
115
class UnknownHTTPResponseError extends Error {
116
code: ClientErrorCode.ResponseError;
117
/** HTTP status code */
118
status: number;
119
/** Response body */
120
body: string;
121
}
122
```
123
124
**Usage Examples:**
125
126
```typescript
127
import { Client, ClientErrorCode } from "@notionhq/client";
128
129
const notion = new Client({
130
auth: process.env.NOTION_TOKEN,
131
timeoutMs: 5000, // 5 second timeout
132
});
133
134
try {
135
const page = await notion.pages.retrieve({
136
page_id: "page-id",
137
});
138
} catch (error) {
139
if (isNotionClientError(error)) {
140
if (error.code === ClientErrorCode.RequestTimeout) {
141
console.log("Request timed out - try again");
142
} else if (error.code === ClientErrorCode.ResponseError) {
143
console.log(`HTTP error ${error.status}: ${error.body}`);
144
}
145
}
146
}
147
```
148
149
### Error Code Union Type
150
151
```typescript { .api }
152
/**
153
* Union of all error codes (API + Client)
154
*/
155
type NotionErrorCode = APIErrorCode | ClientErrorCode;
156
```
157
158
## Error Handling Patterns
159
160
### Basic Error Handling
161
162
```typescript
163
async function safePage Retrieval(pageId: string) {
164
try {
165
const page = await notion.pages.retrieve({ page_id: pageId });
166
return { success: true, page };
167
} catch (error) {
168
if (isNotionClientError(error)) {
169
return {
170
success: false,
171
error: error.code,
172
message: error.message
173
};
174
}
175
176
return {
177
success: false,
178
error: "unknown",
179
message: "Unknown error occurred"
180
};
181
}
182
}
183
```
184
185
### Retry with Exponential Backoff
186
187
```typescript
188
async function retryWithBackoff<T>(
189
operation: () => Promise<T>,
190
maxRetries: number = 3
191
): Promise<T> {
192
let lastError: Error;
193
194
for (let attempt = 0; attempt < maxRetries; attempt++) {
195
try {
196
return await operation();
197
} catch (error) {
198
lastError = error as Error;
199
200
if (isNotionClientError(error)) {
201
// Don't retry certain errors
202
if (error.code === APIErrorCode.Unauthorized ||
203
error.code === APIErrorCode.ObjectNotFound ||
204
error.code === APIErrorCode.InvalidRequest) {
205
throw error;
206
}
207
208
// Retry rate limited or server errors
209
if (error.code === APIErrorCode.RateLimited ||
210
error.code === APIErrorCode.InternalServerError ||
211
error.code === APIErrorCode.ServiceUnavailable ||
212
error.code === ClientErrorCode.RequestTimeout) {
213
214
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
215
await new Promise(resolve => setTimeout(resolve, delay));
216
continue;
217
}
218
}
219
220
throw error;
221
}
222
}
223
224
throw lastError!;
225
}
226
227
// Usage
228
const page = await retryWithBackoff(() =>
229
notion.pages.retrieve({ page_id: "page-id" })
230
);
231
```
232
233
### Detailed Error Information
234
235
```typescript
236
function handleNotionError(error: unknown) {
237
if (!isNotionClientError(error)) {
238
console.log("Non-Notion error:", error);
239
return;
240
}
241
242
console.log(`Error Code: ${error.code}`);
243
console.log(`Error Message: ${error.message}`);
244
245
if (error instanceof APIResponseError) {
246
console.log(`HTTP Status: ${error.status}`);
247
console.log(`Response Headers:`, error.headers);
248
console.log(`Response Body:`, error.body);
249
}
250
251
if (error instanceof UnknownHTTPResponseError) {
252
console.log(`HTTP Status: ${error.status}`);
253
console.log(`Response Body:`, error.body);
254
}
255
256
// Handle specific error codes
257
switch (error.code) {
258
case APIErrorCode.Unauthorized:
259
console.log("Check your API token and permissions");
260
break;
261
case APIErrorCode.RateLimited:
262
console.log("Slow down requests to avoid rate limiting");
263
break;
264
case APIErrorCode.ObjectNotFound:
265
console.log("The requested resource was not found");
266
break;
267
case APIErrorCode.ValidationError:
268
console.log("Request data failed validation");
269
break;
270
case ClientErrorCode.RequestTimeout:
271
console.log("Request timed out - consider increasing timeout");
272
break;
273
}
274
}
275
```
276
277
### Graceful Degradation
278
279
```typescript
280
async function getPageOrFallback(pageId: string) {
281
try {
282
return await notion.pages.retrieve({ page_id: pageId });
283
} catch (error) {
284
if (isNotionClientError(error)) {
285
if (error.code === APIErrorCode.ObjectNotFound) {
286
// Return a default page structure
287
return {
288
object: "page" as const,
289
id: pageId,
290
properties: {},
291
// ... other default properties
292
};
293
}
294
295
if (error.code === APIErrorCode.Unauthorized) {
296
throw new Error("Authentication required");
297
}
298
}
299
300
// Re-throw other errors
301
throw error;
302
}
303
}
304
```
305
306
## Types
307
308
```typescript { .api }
309
enum APIErrorCode {
310
Unauthorized = "unauthorized";
311
RestrictedResource = "restricted_resource";
312
ObjectNotFound = "object_not_found";
313
RateLimited = "rate_limited";
314
InvalidJSON = "invalid_json";
315
InvalidRequestURL = "invalid_request_url";
316
InvalidRequest = "invalid_request";
317
ValidationError = "validation_error";
318
ConflictError = "conflict_error";
319
InternalServerError = "internal_server_error";
320
ServiceUnavailable = "service_unavailable";
321
}
322
323
enum ClientErrorCode {
324
RequestTimeout = "notionhq_client_request_timeout";
325
ResponseError = "notionhq_client_response_error";
326
}
327
328
type NotionErrorCode = APIErrorCode | ClientErrorCode;
329
330
type NotionClientError = APIResponseError | UnknownHTTPResponseError | RequestTimeoutError;
331
332
class APIResponseError extends Error {
333
code: APIErrorCode;
334
status: number;
335
headers: Record<string, string>;
336
body: string;
337
}
338
339
class UnknownHTTPResponseError extends Error {
340
code: ClientErrorCode.ResponseError;
341
status: number;
342
body: string;
343
}
344
345
class RequestTimeoutError extends Error {
346
code: ClientErrorCode.RequestTimeout;
347
}
348
349
function isNotionClientError(error: unknown): error is NotionClientError;
350
```