Skip to content

Node.js SDK - Error Handling

The mailiam Node.js SDK provides comprehensive error handling with specific error types and automatic retries.

The SDK includes specific error classes for different failure scenarios:

import {
mailiam,
AuthenticationError,
RateLimitError,
ValidationError,
NetworkError,
ApiError
} from '@mailiam/node';
try {
await mailiam.emails.send({
from: 'hello@mycompany.com',
to: 'customer@example.com',
subject: 'Test',
html: '<p>Test</p>'
});
} catch (error) {
console.error('Failed to send email:', error.message);
}

Thrown when API key is invalid or missing:

try {
await mailiam.emails.send({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key. Please check your credentials.');
// Update API key or alert administrator
}
}

Thrown when rate limit is exceeded:

try {
await mailiam.emails.send({ ... });
} catch (error) {
if (error instanceof RateLimitError) {
console.error('Rate limit exceeded');
console.log('Retry after:', error.retryAfter, 'seconds');
// Wait and retry, or queue for later
}
}

Thrown when request data is invalid:

try {
await mailiam.emails.send({ ... });
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid email data:', error.message);
console.log('Details:', error.details);
// Fix validation issues
}
}

Thrown when network request fails:

try {
await mailiam.emails.send({ ... });
} catch (error) {
if (error instanceof NetworkError) {
console.error('Network error:', error.message);
// Check network connection or retry
}
}

General API errors with status code:

try {
await mailiam.emails.send({ ... });
} catch (error) {
if (error instanceof ApiError) {
console.error('API error:', error.message);
console.log('Status code:', error.statusCode);
console.log('Error code:', error.code);
console.log('Details:', error.details);
}
}
import {
mailiam,
AuthenticationError,
RateLimitError,
ValidationError,
NetworkError,
ApiError
} from '@mailiam/node';
async function sendEmailWithErrorHandling(emailData) {
try {
const result = await mailiam.emails.send(emailData);
return { success: true, messageId: result.messageId };
} catch (error) {
if (error instanceof AuthenticationError) {
// Critical: Invalid API key
await alertAdmin('Invalid mailiam API key');
return { success: false, error: 'authentication_failed' };
}
if (error instanceof RateLimitError) {
// Temporary: Rate limit hit
await queueForLater(emailData, error.retryAfter);
return { success: false, error: 'rate_limited', retryAfter: error.retryAfter };
}
if (error instanceof ValidationError) {
// Permanent: Bad request data
await logValidationError(emailData, error.details);
return { success: false, error: 'validation_failed', details: error.details };
}
if (error instanceof NetworkError) {
// Temporary: Network issue
await queueForRetry(emailData);
return { success: false, error: 'network_error' };
}
if (error instanceof ApiError) {
// Various API errors
await logApiError(error);
return { success: false, error: 'api_error', statusCode: error.statusCode };
}
// Unknown error
await logUnknownError(error);
return { success: false, error: 'unknown' };
}
}

The SDK automatically retries failed requests with exponential backoff for:

  • Network errors
  • 5xx server errors
  • 429 rate limit errors (with Retry-After header)

Default retry configuration:

  • Max retries: 3
  • Initial delay: 1000ms
  • Max delay: 10000ms
  • Backoff multiplier: 2x
const mailiam = new mailiam({
apiKey: process.env.MAILIAM_API_KEY,
maxRetries: 5 // Increase max retries
});
const mailiam = new mailiam({
apiKey: process.env.MAILIAM_API_KEY,
maxRetries: 0 // Disable automatic retries
});

Batch operations continue even if individual emails fail:

const result = await mailiam.emails.sendBatch(emails);
if (result.failed > 0) {
result.results.forEach((item, index) => {
if (!item.success) {
console.error(`Email ${index} failed:`, item.error);
// Handle specific failures
const email = emails[index];
await handleFailedEmail(email, item.error);
}
});
}
async function sendEmail(data) {
const startTime = Date.now();
try {
const result = await mailiam.emails.send(data);
logger.info('Email sent successfully', {
messageId: result.messageId,
to: data.to,
duration: Date.now() - startTime
});
return result;
} catch (error) {
logger.error('Email send failed', {
error: error.message,
errorType: error.constructor.name,
to: data.to,
duration: Date.now() - startTime
});
throw error;
}
}
async function sendOrQueue(emailData) {
try {
return await mailiam.emails.send(emailData);
} catch (error) {
if (error instanceof RateLimitError || error instanceof NetworkError) {
// Queue for later retry
await emailQueue.add(emailData, {
delay: error.retryAfter ? error.retryAfter * 1000 : 60000
});
return { queued: true };
}
throw error;
}
}
async function sendWithMonitoring(emailData) {
try {
const result = await mailiam.emails.send(emailData);
metrics.increment('email.sent');
return result;
} catch (error) {
if (error instanceof AuthenticationError) {
metrics.increment('email.auth_error');
await alerting.critical('mailiam authentication failed');
} else if (error instanceof RateLimitError) {
metrics.increment('email.rate_limited');
} else {
metrics.increment('email.error');
}
throw error;
}
}

Enable debug mode to see detailed logs:

const mailiam = new mailiam({
apiKey: process.env.MAILIAM_API_KEY,
debug: true // Enable debug logging
});

This will log:

  • Request URLs and methods
  • Request bodies
  • Response status codes
  • Response bodies
  • Retry attempts