0
# Error Handling
1
2
Comprehensive error handling system with specific error types for different failure scenarios and automatic retry mechanisms.
3
4
## Capabilities
5
6
### Error Types
7
8
The SDK provides a hierarchical error system for precise error handling and debugging.
9
10
```typescript { .api }
11
enum QiniuErrorName {
12
// Input validation errors
13
InvalidFile = 'InvalidFile',
14
InvalidToken = 'InvalidToken',
15
InvalidMetadata = 'InvalidMetadata',
16
InvalidChunkSize = 'InvalidChunkSize',
17
InvalidCustomVars = 'InvalidCustomVars',
18
NotAvailableUploadHost = 'NotAvailableUploadHost',
19
20
// Cache and resume functionality errors
21
ReadCacheFailed = 'ReadCacheFailed',
22
InvalidCacheData = 'InvalidCacheData',
23
WriteCacheFailed = 'WriteCacheFailed',
24
RemoveCacheFailed = 'RemoveCacheFailed',
25
26
// Image compression errors
27
GetCanvasContextFailed = 'GetCanvasContextFailed',
28
UnsupportedFileType = 'UnsupportedFileType',
29
30
// Browser environment errors
31
FileReaderReadFailed = 'FileReaderReadFailed',
32
NotAvailableXMLHttpRequest = 'NotAvailableXMLHttpRequest',
33
InvalidProgressEventTarget = 'InvalidProgressEventTarget',
34
35
// Network and server errors
36
RequestError = 'RequestError'
37
}
38
```
39
40
### Base Error Class
41
42
Foundation error class for all SDK errors.
43
44
```typescript { .api }
45
/**
46
* Base error class for all Qiniu SDK errors
47
*/
48
class QiniuError implements Error {
49
public stack: string | undefined;
50
51
constructor(public name: QiniuErrorName, public message: string);
52
}
53
```
54
55
**Usage Example:**
56
57
```typescript
58
import { QiniuError, QiniuErrorName } from "qiniu-js";
59
60
try {
61
// Some SDK operation
62
} catch (error) {
63
if (error instanceof QiniuError) {
64
switch (error.name) {
65
case QiniuErrorName.InvalidFile:
66
console.error('File validation failed:', error.message);
67
break;
68
case QiniuErrorName.InvalidToken:
69
console.error('Token is invalid or expired:', error.message);
70
break;
71
default:
72
console.error('SDK error:', error.message);
73
}
74
}
75
}
76
```
77
78
### Request Error Class
79
80
Specific error type for HTTP request failures with server response details.
81
82
```typescript { .api }
83
/**
84
* Error class for HTTP request failures
85
*/
86
class QiniuRequestError extends QiniuError {
87
/**
88
* Legacy property for error type identification
89
* @deprecated Use instanceof instead
90
*/
91
public isRequestError = true;
92
93
/** Server response data if available */
94
public data?: any;
95
96
constructor(
97
public code: number,
98
public reqId: string,
99
message: string,
100
data?: any
101
);
102
}
103
```
104
105
**Usage Example:**
106
107
```typescript
108
import { upload, QiniuRequestError } from "qiniu-js";
109
110
const subscription = upload(file, key, token).subscribe({
111
error: (error) => {
112
if (error instanceof QiniuRequestError) {
113
console.error(`Request failed with HTTP ${error.code}`);
114
console.error(`Request ID: ${error.reqId}`);
115
116
if (error.data) {
117
console.error('Server response:', error.data);
118
}
119
120
// Handle specific HTTP codes
121
switch (error.code) {
122
case 401:
123
console.error('Unauthorized - check your token');
124
break;
125
case 403:
126
console.error('Forbidden - insufficient permissions');
127
break;
128
case 413:
129
console.error('File too large');
130
break;
131
case 599:
132
console.error('Server timeout - will retry automatically');
133
break;
134
default:
135
console.error('Request error:', error.message);
136
}
137
}
138
}
139
});
140
```
141
142
### Network Error Class
143
144
Specialized error for network connectivity issues.
145
146
```typescript { .api }
147
/**
148
* Error class for network connectivity issues
149
* Covers CORS, certificate, DNS, and connection failures
150
*/
151
class QiniuNetworkError extends QiniuRequestError {
152
constructor(message: string, reqId?: string);
153
}
154
```
155
156
**Usage Example:**
157
158
```typescript
159
import { upload, QiniuNetworkError, QiniuRequestError } from "qiniu-js";
160
161
const subscription = upload(file, key, token).subscribe({
162
error: (error) => {
163
if (error instanceof QiniuNetworkError) {
164
console.error('Network connectivity issue:', error.message);
165
// Suggest user checks connection, firewall, etc.
166
showNetworkErrorMessage();
167
} else if (error instanceof QiniuRequestError) {
168
console.error('Server request failed:', error.message);
169
// Handle server-side errors
170
} else {
171
console.error('Other error:', error.message);
172
// Handle validation and other errors
173
}
174
}
175
});
176
```
177
178
## Error Handling Patterns
179
180
### Comprehensive Error Handling
181
182
Complete error handling strategy covering all error types.
183
184
```typescript
185
import {
186
upload,
187
QiniuError,
188
QiniuRequestError,
189
QiniuNetworkError,
190
QiniuErrorName
191
} from "qiniu-js";
192
193
function handleUpload(file: File, key: string, token: string) {
194
const subscription = upload(file, key, token, {
195
fname: file.name
196
}, {
197
retryCount: 3,
198
region: 'z0'
199
}).subscribe({
200
next: (progress) => {
201
updateProgressUI(progress.total.percent);
202
},
203
error: (error) => {
204
if (error instanceof QiniuNetworkError) {
205
// Network issues - suggest user actions
206
showErrorMessage('Network connection failed. Please check your internet connection and try again.');
207
logError('network', error);
208
209
} else if (error instanceof QiniuRequestError) {
210
// Server errors - handle based on HTTP code
211
const isRetryable = [502, 503, 504, 599].includes(error.code);
212
213
if (isRetryable) {
214
showErrorMessage('Server temporarily unavailable. The upload will retry automatically.');
215
} else if (error.code === 401) {
216
showErrorMessage('Upload token expired. Please refresh and try again.');
217
refreshToken();
218
} else if (error.code === 413) {
219
showErrorMessage('File is too large for upload.');
220
} else {
221
showErrorMessage(`Upload failed: ${error.message}`);
222
}
223
224
logError('request', error, { code: error.code, reqId: error.reqId });
225
226
} else if (error instanceof QiniuError) {
227
// SDK validation and runtime errors
228
switch (error.name) {
229
case QiniuErrorName.InvalidFile:
230
showErrorMessage('Invalid file selected. Please choose a different file.');
231
break;
232
case QiniuErrorName.InvalidToken:
233
showErrorMessage('Upload token is invalid. Please refresh and try again.');
234
refreshToken();
235
break;
236
case QiniuErrorName.UnsupportedFileType:
237
showErrorMessage('File type not supported for compression.');
238
break;
239
case QiniuErrorName.GetCanvasContextFailed:
240
showErrorMessage('Image processing failed. Browser may not support required features.');
241
break;
242
default:
243
showErrorMessage(`Upload failed: ${error.message}`);
244
}
245
246
logError('sdk', error);
247
248
} else {
249
// Unexpected errors
250
showErrorMessage('An unexpected error occurred. Please try again.');
251
logError('unknown', error);
252
}
253
},
254
complete: (response) => {
255
showSuccessMessage('File uploaded successfully!');
256
console.log('Upload result:', response);
257
}
258
});
259
260
return subscription;
261
}
262
263
// Helper functions
264
function showErrorMessage(message: string) {
265
// Update UI with error message
266
document.getElementById('error-message').textContent = message;
267
}
268
269
function showSuccessMessage(message: string) {
270
// Update UI with success message
271
document.getElementById('success-message').textContent = message;
272
}
273
274
function updateProgressUI(percent: number) {
275
// Update progress bar
276
document.getElementById('progress-bar').style.width = `${percent}%`;
277
}
278
279
function logError(type: string, error: any, extra?: any) {
280
// Send error to logging service
281
console.error(`[${type}] Upload error:`, error, extra);
282
}
283
284
function refreshToken() {
285
// Request new token from server
286
// Implementation depends on your authentication system
287
}
288
```
289
290
### Retry Logic and Error Recovery
291
292
The SDK automatically handles retries for certain error conditions:
293
294
```typescript
295
// Errors that trigger automatic retry
296
const RETRY_CODE_LIST = [0, 502, 503, 504, 599, 406];
297
298
// Errors that cause host switching
299
const FREEZE_CODE_LIST = [0, 502, 503, 504, 599];
300
```
301
302
**Custom Retry Configuration:**
303
304
```typescript
305
import { upload } from "qiniu-js";
306
307
// Configure retry behavior
308
const uploadWithRetry = upload(file, key, token, {
309
fname: file.name
310
}, {
311
retryCount: 5, // Retry up to 5 times
312
region: 'z0'
313
}).subscribe({
314
error: (error) => {
315
if (error instanceof QiniuRequestError) {
316
console.log(`Failed after ${5} retry attempts`);
317
}
318
}
319
});
320
```
321
322
### Validation Error Prevention
323
324
Prevent common validation errors by checking inputs before upload:
325
326
```typescript
327
import { QiniuError, QiniuErrorName } from "qiniu-js";
328
329
function validateUploadInputs(file: File, token: string, putExtra?: any): string | null {
330
// File validation
331
if (!file || file.size === 0) {
332
return 'Please select a valid file';
333
}
334
335
if (file.size > 10000 * 1024 * 1024 * 1024) { // 10TB limit
336
return 'File size exceeds maximum limit of 10TB';
337
}
338
339
// Token validation
340
if (!token || typeof token !== 'string') {
341
return 'Upload token is required';
342
}
343
344
// Custom variables validation
345
if (putExtra?.customVars) {
346
for (const key of Object.keys(putExtra.customVars)) {
347
if (!key.startsWith('x:')) {
348
return `Custom variable key '${key}' must start with 'x:'`;
349
}
350
}
351
}
352
353
// Metadata validation
354
if (putExtra?.metadata) {
355
for (const key of Object.keys(putExtra.metadata)) {
356
if (!key.startsWith('x-qn-meta-')) {
357
return `Metadata key '${key}' must start with 'x-qn-meta-'`;
358
}
359
}
360
}
361
362
return null; // No validation errors
363
}
364
365
// Use validation before upload
366
function safeUpload(file: File, key: string, token: string, putExtra?: any) {
367
const validationError = validateUploadInputs(file, token, putExtra);
368
369
if (validationError) {
370
console.error('Validation failed:', validationError);
371
return;
372
}
373
374
return upload(file, key, token, putExtra);
375
}
376
```