Node.js client for the Tinify API that intelligently compresses, resizes, converts, and stores images in AVIF, WebP, JPEG, and PNG formats.
—
Comprehensive error types for different failure scenarios including authentication, client, server, and connection errors.
Tinify provides a structured error hierarchy for different types of failures.
/**
* Base error class for all Tinify errors
*/
class Error extends globalThis.Error {
/** HTTP status code if available */
status?: number;
/**
* Create a new Tinify error
* @param message - Error message
* @param type - Error type string
* @param status - HTTP status code
*/
constructor(message: string, type?: string, status?: number);
/**
* Factory method to create appropriate error subclass
* @param message - Error message
* @param type - Error type from API
* @param status - HTTP status code
* @returns Appropriate error subclass instance
*/
static create(message: string, type: string, status?: number): Error;
}
/**
* Account-related errors (authentication, billing, limits)
* Thrown for HTTP status codes 401 and 429
*/
class AccountError extends Error {}
/**
* Client-side errors (invalid input, bad requests)
* Thrown for HTTP status codes 400-499 (except 401, 429)
*/
class ClientError extends Error {}
/**
* Server-side errors (API service issues)
* Thrown for HTTP status codes 500-599
*/
class ServerError extends Error {}
/**
* Network connectivity errors
* Thrown for connection failures, timeouts, proxy issues
*/
class ConnectionError extends Error {}Handle authentication, billing, and API usage limit issues.
Common Account Error Scenarios:
Usage Examples:
const tinify = require("tinify");
// Invalid API key
tinify.key = "invalid-key";
try {
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
} catch (error) {
if (error instanceof tinify.AccountError) {
if (error.status === 401) {
console.error("Invalid API key:", error.message);
// Prompt user to check their API key
} else if (error.status === 429) {
console.error("Monthly limit exceeded:", error.message);
// Handle billing upgrade or wait for next month
}
}
}
// Check compression count to avoid limits
tinify.key = "valid-api-key";
try {
await tinify.validate();
console.log(`Compressions used: ${tinify.compressionCount}`);
if (tinify.compressionCount && tinify.compressionCount > 450) {
console.warn("Approaching monthly limit!");
}
} catch (error) {
if (error instanceof tinify.AccountError) {
console.error("Account validation failed:", error.message);
}
}Handle invalid input, unsupported formats, and malformed requests.
Common Client Error Scenarios:
Usage Examples:
const tinify = require("tinify");
tinify.key = "your-api-key";
try {
// Invalid file path
await tinify.fromFile("nonexistent-file.jpg").toFile("output.jpg");
} catch (error) {
if (error instanceof tinify.ClientError) {
console.error("Client error:", error.message);
if (error.status === 400) {
console.error("Bad request - check input parameters");
} else if (error.status === 415) {
console.error("Unsupported image format");
}
}
}
try {
// Invalid transformation options
await tinify.fromFile("image.jpg")
.resize({ method: "invalid-method", width: -100 })
.toFile("output.jpg");
} catch (error) {
if (error instanceof tinify.ClientError) {
console.error("Invalid resize options:", error.message);
}
}
try {
// Invalid URL
await tinify.fromUrl("not-a-valid-url").toFile("output.jpg");
} catch (error) {
if (error instanceof tinify.ClientError) {
console.error("Invalid URL provided:", error.message);
}
}Handle temporary API service issues and server-side problems.
Common Server Error Scenarios:
Usage Examples:
const tinify = require("tinify");
tinify.key = "your-api-key";
try {
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
} catch (error) {
if (error instanceof tinify.ServerError) {
console.error("Server error:", error.message);
if (error.status === 500) {
console.error("Internal server error - try again later");
} else if (error.status === 502 || error.status === 503) {
console.error("Service temporarily unavailable");
}
// Implement retry logic for server errors
setTimeout(async () => {
try {
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
console.log("Retry successful");
} catch (retryError) {
console.error("Retry failed:", retryError.message);
}
}, 5000);
}
}Handle network connectivity, proxy, and timeout issues.
Common Connection Error Scenarios:
Usage Examples:
const tinify = require("tinify");
tinify.key = "your-api-key";
tinify.proxy = "http://proxy.example.com:8080";
try {
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
} catch (error) {
if (error instanceof tinify.ConnectionError) {
console.error("Connection error:", error.message);
// Check different potential causes
if (error.message.includes("ENOTFOUND")) {
console.error("DNS resolution failed - check network connectivity");
} else if (error.message.includes("ECONNREFUSED")) {
console.error("Connection refused - check proxy settings");
} else if (error.message.includes("timeout")) {
console.error("Request timeout - check network speed");
}
// Suggest troubleshooting steps
console.log("Troubleshooting suggestions:");
console.log("1. Check internet connectivity");
console.log("2. Verify proxy settings");
console.log("3. Try again without proxy");
// Retry without proxy
try {
tinify.proxy = "";
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
console.log("Success without proxy");
} catch (retryError) {
console.error("Still failing without proxy:", retryError.message);
}
}
}Best practices for handling all error types in production applications.
Usage Example:
const tinify = require("tinify");
tinify.key = "your-api-key";
async function processImage(inputPath: string, outputPath: string, maxRetries = 3): Promise<boolean> {
let retries = 0;
while (retries < maxRetries) {
try {
await tinify.fromFile(inputPath)
.resize({ method: "fit", width: 1200 })
.toFile(outputPath);
console.log(`Successfully processed: ${outputPath}`);
return true;
} catch (error) {
if (error instanceof tinify.AccountError) {
if (error.status === 401) {
console.error("Invalid API key - check configuration");
return false; // Don't retry for auth errors
} else if (error.status === 429) {
console.error("Monthly limit exceeded");
return false; // Don't retry for limit errors
}
} else if (error instanceof tinify.ClientError) {
console.error(`Client error: ${error.message}`);
return false; // Don't retry for client errors
} else if (error instanceof tinify.ServerError) {
console.error(`Server error (attempt ${retries + 1}): ${error.message}`);
retries++;
if (retries < maxRetries) {
const delay = Math.pow(2, retries) * 1000; // Exponential backoff
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
} else if (error instanceof tinify.ConnectionError) {
console.error(`Connection error (attempt ${retries + 1}): ${error.message}`);
retries++;
if (retries < maxRetries) {
const delay = 2000; // Fixed delay for connection errors
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
} else {
console.error(`Unexpected error: ${error.message}`);
return false;
}
}
}
console.error(`Failed to process image after ${maxRetries} attempts`);
return false;
}
// Usage
const success = await processImage("input.jpg", "output.jpg");
if (!success) {
console.error("Image processing failed permanently");
}Common HTTP status codes and their corresponding error types:
Account Errors:
401: Unauthorized (invalid API key)429: Too Many Requests (monthly limit exceeded)Client Errors:
400: Bad Request (invalid parameters)415: Unsupported Media Type (invalid image format)Server Errors:
500: Internal Server Error502: Bad Gateway503: Service UnavailableConnection Errors:
Error Inspection Example:
const tinify = require("tinify");
tinify.key = "your-api-key";
try {
await tinify.fromFile("image.jpg").toFile("compressed.jpg");
} catch (error) {
console.log(`Error type: ${error.constructor.name}`);
console.log(`Error message: ${error.message}`);
if (error.status) {
console.log(`HTTP status: ${error.status}`);
}
// Type-specific handling
switch (error.constructor.name) {
case 'AccountError':
console.log("Account-related issue");
break;
case 'ClientError':
console.log("Client-side issue");
break;
case 'ServerError':
console.log("Server-side issue");
break;
case 'ConnectionError':
console.log("Network connectivity issue");
break;
default:
console.log("Unknown error type");
}
}Install with Tessl CLI
npx tessl i tessl/npm-tinify