Error Handling
The SDK provides typed exceptions for different error scenarios.
Exception Hierarchy
NovelAIError (base)
├── MissingAPIKeyError
├── AuthenticationError
├── InvalidRequestError
├── RateLimitError
├── ServerError
├── NetworkError
└── FileNotFoundErrorException Types
NovelAIError
Base class for all SDK errors.
typescript
import { NovelAIError } from 'novelai-sdk-unofficial';
try {
// SDK operation
} catch (error) {
if (error instanceof NovelAIError) {
console.error('SDK error:', error.message);
}
}MissingAPIKeyError
Thrown when no API key is provided.
typescript
import { NovelAI, MissingAPIKeyError } from 'novelai-sdk-unofficial';
try {
const client = new NovelAI(); // No key, no env var
} catch (error) {
if (error instanceof MissingAPIKeyError) {
console.error('Please set NOVELAI_API_KEY or provide apiKey option');
}
}AuthenticationError
Thrown for authentication failures (HTTP 401, 402).
- Invalid API key
- Expired API key
- Insufficient credits/subscription
typescript
import { AuthenticationError } from 'novelai-sdk-unofficial';
try {
await client.image.generate({ prompt: 'test' });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Check your API key and subscription status');
}
}InvalidRequestError
Thrown for invalid request parameters (HTTP 400).
typescript
import { InvalidRequestError } from 'novelai-sdk-unofficial';
try {
await client.image.generate({
prompt: 'test',
size: [100, 100], // Invalid: not multiple of 64
});
} catch (error) {
if (error instanceof InvalidRequestError) {
console.error('Invalid parameters:', error.message);
}
}RateLimitError
Thrown when rate limit is exceeded (HTTP 429).
typescript
import { RateLimitError } from 'novelai-sdk-unofficial';
try {
await client.image.generate({ prompt: 'test' });
} catch (error) {
if (error instanceof RateLimitError) {
console.error('Rate limited. Please wait before retrying.');
// Implement backoff strategy
}
}ServerError
Thrown for server-side errors (HTTP 5xx).
typescript
import { ServerError } from 'novelai-sdk-unofficial';
try {
await client.image.generate({ prompt: 'test' });
} catch (error) {
if (error instanceof ServerError) {
console.error('Server error. Try again later.');
}
}NetworkError
Thrown for network-related failures.
- Connection timeout
- DNS resolution failure
- Connection refused
typescript
import { NetworkError } from 'novelai-sdk-unofficial';
try {
await client.image.generate({ prompt: 'test' });
} catch (error) {
if (error instanceof NetworkError) {
console.error('Network error. Check your connection.');
}
}FileNotFoundError
Thrown when a referenced file doesn't exist.
typescript
import { FileNotFoundError } from 'novelai-sdk-unofficial';
try {
// If using file path that doesn't exist
} catch (error) {
if (error instanceof FileNotFoundError) {
console.error('File not found:', error.message);
}
}Comprehensive Error Handling
typescript
import {
NovelAI,
NovelAIError,
MissingAPIKeyError,
AuthenticationError,
InvalidRequestError,
RateLimitError,
ServerError,
NetworkError,
} from 'novelai-sdk-unofficial';
async function generateImage(prompt: string) {
try {
const client = new NovelAI();
const images = await client.image.generate({ prompt });
return images[0];
} catch (error) {
if (error instanceof MissingAPIKeyError) {
throw new Error('Configuration error: API key not set');
}
if (error instanceof AuthenticationError) {
throw new Error('Authentication failed: Check API key');
}
if (error instanceof InvalidRequestError) {
throw new Error(`Invalid request: ${error.message}`);
}
if (error instanceof RateLimitError) {
// Could implement retry with backoff
throw new Error('Rate limited: Try again later');
}
if (error instanceof ServerError) {
throw new Error('Server error: Service temporarily unavailable');
}
if (error instanceof NetworkError) {
throw new Error('Network error: Check connection');
}
if (error instanceof NovelAIError) {
throw new Error(`SDK error: ${error.message}`);
}
throw error; // Re-throw unknown errors
}
}Retry Strategy
Example with exponential backoff for rate limits:
typescript
async function generateWithRetry(
prompt: string,
maxRetries: number = 3
): Promise<Buffer> {
let lastError: Error | undefined;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const images = await client.image.generate({ prompt });
return images[0];
} catch (error) {
if (error instanceof RateLimitError) {
lastError = error;
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error; // Don't retry other errors
}
}
throw lastError;
}Validation Errors
The SDK uses Zod for parameter validation. Invalid parameters throw ZodError:
typescript
import { z } from 'zod';
try {
await client.image.generate({
prompt: '', // Empty prompt
});
} catch (error) {
if (error instanceof z.ZodError) {
console.error('Validation errors:');
error.errors.forEach(e => {
console.error(` ${e.path.join('.')}: ${e.message}`);
});
}
}