Skip to content

Errors

Meloqui provides a hierarchy of typed errors for handling different failure scenarios.

ChatError

Base class for all chat-related errors.

typescript
class ChatError extends Error {
  readonly isRetryable: boolean;
  readonly provider?: string;
  readonly originalError?: Error;

  constructor(
    message: string,
    provider?: string,
    originalError?: Error,
    isRetryable?: boolean
  );
}
PropertyTypeDescription
isRetryablebooleanWhether the request can be retried
providerstringProvider that threw the error
originalErrorErrorUnderlying error from the provider SDK

Retryable Errors

These errors have isRetryable: true and can succeed if retried:

RateLimitError

Thrown when rate limit is exceeded.

typescript
import { ChatClient, RateLimitError } from 'meloqui';

try {
  await client.chat('Hello');
} catch (error) {
  if (error instanceof RateLimitError) {
    // Wait and retry, or enable automatic retry
  }
}

TimeoutError

Thrown when request times out.

typescript
import { TimeoutError } from 'meloqui';

try {
  await client.chat('Hello', { timeout: 5000 });
} catch (error) {
  if (error instanceof TimeoutError) {
    // Request took too long
  }
}

ServerError

Thrown when the provider returns a server error (5xx).

typescript
import { ServerError } from 'meloqui';
// isRetryable: true - server issues may be transient

RagRetrievalError

Thrown when RAG context retrieval fails.

typescript
import { RagRetrievalError } from 'meloqui';
// isRetryable: true - embedding services may recover

Non-Retryable Errors

These errors require fixing before retrying:

AuthenticationError

Thrown when authentication fails (invalid API key).

typescript
import { AuthenticationError } from 'meloqui';

try {
  await client.chat('Hello');
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Check API key configuration
  }
}

InvalidRequestError

Thrown when request parameters are invalid.

typescript
import { InvalidRequestError } from 'meloqui';
// Fix the request parameters before retrying

ModelNotFoundError

Thrown when the specified model doesn't exist.

typescript
import { ModelNotFoundError } from 'meloqui';
// Correct the model name in configuration

InvalidConversationIdError

Thrown when a conversation ID is invalid or contains dangerous patterns.

typescript
import { InvalidConversationIdError } from 'meloqui';
// Conversation ID contains path traversal or invalid characters

CapabilityError

Thrown when using a capability the provider doesn't support.

typescript
import { ChatClient, CapabilityError } from 'meloqui';

try {
  await client.chat({
    role: 'user',
    content: [{ type: 'image', image: './photo.jpg' }]
  });
} catch (error) {
  if (error instanceof CapabilityError) {
    console.log(`${error.provider} doesn't support ${error.capability}`);
  }
}
PropertyTypeDescription
capabilitystringThe unsupported capability (e.g., "vision")

PluginError

Thrown when a provider plugin is misconfigured or invalid.

typescript
import { PluginError } from 'meloqui';
// Check plugin configuration

StorageError

Thrown when a storage operation fails.

typescript
import { StorageError } from 'meloqui';

try {
  const messages = await storage.load('conversation-123');
} catch (error) {
  if (error instanceof StorageError) {
    console.log(`Operation "${error.operation}" failed`);
    console.log(`Conversation: ${error.conversationId}`);
  }
}
PropertyTypeDescription
operationstringThe failed operation (save, load, delete, list)
conversationIdstringThe conversation ID involved

Error Handling Patterns

Comprehensive Error Handling

typescript
import {
  ChatClient,
  ChatError,
  RateLimitError,
  AuthenticationError,
  TimeoutError,
  CapabilityError
} from 'meloqui';

try {
  await client.chat('Hello');
} catch (error) {
  if (error instanceof RateLimitError) {
    // Wait and retry
  } else if (error instanceof AuthenticationError) {
    // Check API key
  } else if (error instanceof TimeoutError) {
    // Increase timeout or retry
  } else if (error instanceof CapabilityError) {
    // Fall back to text-only
  } else if (error instanceof ChatError) {
    // Generic chat error
    if (error.isRetryable) {
      // Safe to retry
    }
  } else {
    // Unknown error
    throw error;
  }
}

With Automatic Retry

Configure RetryManager to automatically handle retryable errors:

typescript
const client = new ChatClient({
  provider: 'openai',
  model: 'gpt-4o',
  retryConfig: {
    maxAttempts: 3,
    initialBackoffMs: 1000,
    maxBackoffMs: 10000,
    backoffMultiplier: 2
  }
});

See RetryManager for details.

Released under the MIT License.