0
# Error Handling
1
2
Comprehensive error types for different failure scenarios including authentication, client, server, and connection errors.
3
4
## Capabilities
5
6
### Error Class Hierarchy
7
8
Tinify provides a structured error hierarchy for different types of failures.
9
10
```typescript { .api }
11
/**
12
* Base error class for all Tinify errors
13
*/
14
class Error extends globalThis.Error {
15
/** HTTP status code if available */
16
status?: number;
17
18
/**
19
* Create a new Tinify error
20
* @param message - Error message
21
* @param type - Error type string
22
* @param status - HTTP status code
23
*/
24
constructor(message: string, type?: string, status?: number);
25
26
/**
27
* Factory method to create appropriate error subclass
28
* @param message - Error message
29
* @param type - Error type from API
30
* @param status - HTTP status code
31
* @returns Appropriate error subclass instance
32
*/
33
static create(message: string, type: string, status?: number): Error;
34
}
35
36
/**
37
* Account-related errors (authentication, billing, limits)
38
* Thrown for HTTP status codes 401 and 429
39
*/
40
class AccountError extends Error {}
41
42
/**
43
* Client-side errors (invalid input, bad requests)
44
* Thrown for HTTP status codes 400-499 (except 401, 429)
45
*/
46
class ClientError extends Error {}
47
48
/**
49
* Server-side errors (API service issues)
50
* Thrown for HTTP status codes 500-599
51
*/
52
class ServerError extends Error {}
53
54
/**
55
* Network connectivity errors
56
* Thrown for connection failures, timeouts, proxy issues
57
*/
58
class ConnectionError extends Error {}
59
```
60
61
### Account Errors
62
63
Handle authentication, billing, and API usage limit issues.
64
65
**Common Account Error Scenarios:**
66
67
- Invalid or missing API key
68
- Monthly compression limit exceeded
69
- Account suspension or billing issues
70
- Rate limiting (too many requests)
71
72
**Usage Examples:**
73
74
```typescript
75
const tinify = require("tinify");
76
77
// Invalid API key
78
tinify.key = "invalid-key";
79
80
try {
81
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
82
} catch (error) {
83
if (error instanceof tinify.AccountError) {
84
if (error.status === 401) {
85
console.error("Invalid API key:", error.message);
86
// Prompt user to check their API key
87
} else if (error.status === 429) {
88
console.error("Monthly limit exceeded:", error.message);
89
// Handle billing upgrade or wait for next month
90
}
91
}
92
}
93
94
// Check compression count to avoid limits
95
tinify.key = "valid-api-key";
96
97
try {
98
await tinify.validate();
99
console.log(`Compressions used: ${tinify.compressionCount}`);
100
101
if (tinify.compressionCount && tinify.compressionCount > 450) {
102
console.warn("Approaching monthly limit!");
103
}
104
} catch (error) {
105
if (error instanceof tinify.AccountError) {
106
console.error("Account validation failed:", error.message);
107
}
108
}
109
```
110
111
### Client Errors
112
113
Handle invalid input, unsupported formats, and malformed requests.
114
115
**Common Client Error Scenarios:**
116
117
- Invalid file format or corrupted image
118
- Unsupported transformation parameters
119
- Invalid URLs or file paths
120
- Malformed configuration options
121
122
**Usage Examples:**
123
124
```typescript
125
const tinify = require("tinify");
126
127
tinify.key = "your-api-key";
128
129
try {
130
// Invalid file path
131
await tinify.fromFile("nonexistent-file.jpg").toFile("output.jpg");
132
} catch (error) {
133
if (error instanceof tinify.ClientError) {
134
console.error("Client error:", error.message);
135
136
if (error.status === 400) {
137
console.error("Bad request - check input parameters");
138
} else if (error.status === 415) {
139
console.error("Unsupported image format");
140
}
141
}
142
}
143
144
try {
145
// Invalid transformation options
146
await tinify.fromFile("image.jpg")
147
.resize({ method: "invalid-method", width: -100 })
148
.toFile("output.jpg");
149
} catch (error) {
150
if (error instanceof tinify.ClientError) {
151
console.error("Invalid resize options:", error.message);
152
}
153
}
154
155
try {
156
// Invalid URL
157
await tinify.fromUrl("not-a-valid-url").toFile("output.jpg");
158
} catch (error) {
159
if (error instanceof tinify.ClientError) {
160
console.error("Invalid URL provided:", error.message);
161
}
162
}
163
```
164
165
### Server Errors
166
167
Handle temporary API service issues and server-side problems.
168
169
**Common Server Error Scenarios:**
170
171
- Temporary API service outages
172
- Server overload or maintenance
173
- Internal processing errors
174
175
**Usage Examples:**
176
177
```typescript
178
const tinify = require("tinify");
179
180
tinify.key = "your-api-key";
181
182
try {
183
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
184
} catch (error) {
185
if (error instanceof tinify.ServerError) {
186
console.error("Server error:", error.message);
187
188
if (error.status === 500) {
189
console.error("Internal server error - try again later");
190
} else if (error.status === 502 || error.status === 503) {
191
console.error("Service temporarily unavailable");
192
}
193
194
// Implement retry logic for server errors
195
setTimeout(async () => {
196
try {
197
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
198
console.log("Retry successful");
199
} catch (retryError) {
200
console.error("Retry failed:", retryError.message);
201
}
202
}, 5000);
203
}
204
}
205
```
206
207
### Connection Errors
208
209
Handle network connectivity, proxy, and timeout issues.
210
211
**Common Connection Error Scenarios:**
212
213
- Network connectivity problems
214
- Proxy configuration issues
215
- Request timeouts
216
- DNS resolution failures
217
218
**Usage Examples:**
219
220
```typescript
221
const tinify = require("tinify");
222
223
tinify.key = "your-api-key";
224
tinify.proxy = "http://proxy.example.com:8080";
225
226
try {
227
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
228
} catch (error) {
229
if (error instanceof tinify.ConnectionError) {
230
console.error("Connection error:", error.message);
231
232
// Check different potential causes
233
if (error.message.includes("ENOTFOUND")) {
234
console.error("DNS resolution failed - check network connectivity");
235
} else if (error.message.includes("ECONNREFUSED")) {
236
console.error("Connection refused - check proxy settings");
237
} else if (error.message.includes("timeout")) {
238
console.error("Request timeout - check network speed");
239
}
240
241
// Suggest troubleshooting steps
242
console.log("Troubleshooting suggestions:");
243
console.log("1. Check internet connectivity");
244
console.log("2. Verify proxy settings");
245
console.log("3. Try again without proxy");
246
247
// Retry without proxy
248
try {
249
tinify.proxy = "";
250
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
251
console.log("Success without proxy");
252
} catch (retryError) {
253
console.error("Still failing without proxy:", retryError.message);
254
}
255
}
256
}
257
```
258
259
### Comprehensive Error Handling
260
261
Best practices for handling all error types in production applications.
262
263
**Usage Example:**
264
265
```typescript
266
const tinify = require("tinify");
267
268
tinify.key = "your-api-key";
269
270
async function processImage(inputPath: string, outputPath: string, maxRetries = 3): Promise<boolean> {
271
let retries = 0;
272
273
while (retries < maxRetries) {
274
try {
275
await tinify.fromFile(inputPath)
276
.resize({ method: "fit", width: 1200 })
277
.toFile(outputPath);
278
279
console.log(`Successfully processed: ${outputPath}`);
280
return true;
281
282
} catch (error) {
283
if (error instanceof tinify.AccountError) {
284
if (error.status === 401) {
285
console.error("Invalid API key - check configuration");
286
return false; // Don't retry for auth errors
287
} else if (error.status === 429) {
288
console.error("Monthly limit exceeded");
289
return false; // Don't retry for limit errors
290
}
291
292
} else if (error instanceof tinify.ClientError) {
293
console.error(`Client error: ${error.message}`);
294
return false; // Don't retry for client errors
295
296
} else if (error instanceof tinify.ServerError) {
297
console.error(`Server error (attempt ${retries + 1}): ${error.message}`);
298
retries++;
299
300
if (retries < maxRetries) {
301
const delay = Math.pow(2, retries) * 1000; // Exponential backoff
302
console.log(`Retrying in ${delay}ms...`);
303
await new Promise(resolve => setTimeout(resolve, delay));
304
}
305
306
} else if (error instanceof tinify.ConnectionError) {
307
console.error(`Connection error (attempt ${retries + 1}): ${error.message}`);
308
retries++;
309
310
if (retries < maxRetries) {
311
const delay = 2000; // Fixed delay for connection errors
312
console.log(`Retrying in ${delay}ms...`);
313
await new Promise(resolve => setTimeout(resolve, delay));
314
}
315
316
} else {
317
console.error(`Unexpected error: ${error.message}`);
318
return false;
319
}
320
}
321
}
322
323
console.error(`Failed to process image after ${maxRetries} attempts`);
324
return false;
325
}
326
327
// Usage
328
const success = await processImage("input.jpg", "output.jpg");
329
if (!success) {
330
console.error("Image processing failed permanently");
331
}
332
```
333
334
### Error Status Codes
335
336
Common HTTP status codes and their corresponding error types:
337
338
**Account Errors:**
339
- `401`: Unauthorized (invalid API key)
340
- `429`: Too Many Requests (monthly limit exceeded)
341
342
**Client Errors:**
343
- `400`: Bad Request (invalid parameters)
344
- `415`: Unsupported Media Type (invalid image format)
345
346
**Server Errors:**
347
- `500`: Internal Server Error
348
- `502`: Bad Gateway
349
- `503`: Service Unavailable
350
351
**Connection Errors:**
352
- No status code (network-level failures)
353
354
**Error Inspection Example:**
355
356
```typescript
357
const tinify = require("tinify");
358
359
tinify.key = "your-api-key";
360
361
try {
362
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
363
} catch (error) {
364
console.log(`Error type: ${error.constructor.name}`);
365
console.log(`Error message: ${error.message}`);
366
367
if (error.status) {
368
console.log(`HTTP status: ${error.status}`);
369
}
370
371
// Type-specific handling
372
switch (error.constructor.name) {
373
case 'AccountError':
374
console.log("Account-related issue");
375
break;
376
case 'ClientError':
377
console.log("Client-side issue");
378
break;
379
case 'ServerError':
380
console.log("Server-side issue");
381
break;
382
case 'ConnectionError':
383
console.log("Network connectivity issue");
384
break;
385
default:
386
console.log("Unknown error type");
387
}
388
}
389
```