Skip to main content

Error Handling

All SDK methods throw typed errors on failure. Every error class extends MemsolusError, so you can catch all SDK errors with a single instanceof check or handle specific cases individually.


Error hierarchy

MemsolusError
├── NotFoundError (404)
├── ValidationError (422)
├── QuotaExceededError (429) — plan quota reached
├── UnauthorizedError (401)
├── ForbiddenError (403)
├── ConflictError (409)
├── TimeoutError
└── NetworkError

Error classes

MemsolusError

Base class for all SDK errors. Always available as a fallback.

class MemsolusError extends Error {
statusCode: number; // HTTP status code
code?: string; // API error code, when available
message: string; // Human-readable error message
}

NotFoundError

Thrown when the requested resource does not exist or does not belong to the current workspace.

class NotFoundError extends MemsolusError {
statusCode: 404;
}
import { NotFoundError } from '@memsolus/sdk';

try {
const memory = await client.memories.get({ id: 'non-existent-id' });
} catch (error) {
if (error instanceof NotFoundError) {
console.log('Memory not found:', error.message);
// Handle gracefully — e.g., inform the user or skip
}
}

ValidationError

Thrown when the request payload fails validation. The code field identifies which field or rule failed.

class ValidationError extends MemsolusError {
statusCode: 422;
code?: string; // e.g., "CONTENT_TOO_LONG", "INVALID_PRIORITY"
}
import { ValidationError } from '@memsolus/sdk';

try {
await client.memories.create({
content: '', // empty content is not allowed
userId: 'user_123',
});
} catch (error) {
if (error instanceof ValidationError) {
console.log('Validation failed:', error.message);
console.log('Error code:', error.code);
}
}

QuotaExceededError

Thrown when a plan quota is reached. The resource field identifies which limit was hit, and limit and used show the current usage.

class QuotaExceededError extends MemsolusError {
statusCode: 429;
resource: string; // e.g., "memories", "searches", "tokens"
limit: number; // maximum allowed
used: number; // current usage
}
import { QuotaExceededError } from '@memsolus/sdk';

try {
await client.memories.create({ content: 'New fact', userId: 'user_123' });
} catch (error) {
if (error instanceof QuotaExceededError) {
console.log(`Quota exceeded for: ${error.resource}`);
console.log(`Used ${error.used} of ${error.limit}`);
// Prompt the user to upgrade, or queue for later
}
}

UnauthorizedError

Thrown when the API key is missing, expired, or invalid.

class UnauthorizedError extends MemsolusError {
statusCode: 401;
}
import { UnauthorizedError } from '@memsolus/sdk';

try {
await client.memories.list();
} catch (error) {
if (error instanceof UnauthorizedError) {
console.log('Invalid or expired API key');
// Redirect to re-authentication or log the error
}
}

ForbiddenError

Thrown when the API key does not have permission for the requested operation.

class ForbiddenError extends MemsolusError {
statusCode: 403;
}
import { ForbiddenError } from '@memsolus/sdk';

try {
await client.memories.delete({ id: 'memory-uuid' });
} catch (error) {
if (error instanceof ForbiddenError) {
console.log('The API key does not have memory.delete permission');
}
}

ConflictError

Thrown when the request conflicts with the current state of a resource.

class ConflictError extends MemsolusError {
statusCode: 409;
}

TimeoutError

Thrown when the request exceeds the configured timeout.

class TimeoutError extends MemsolusError {}
import { TimeoutError } from '@memsolus/sdk';

try {
await client.memories.search({ query: 'complex query', userId: 'user_123' });
} catch (error) {
if (error instanceof TimeoutError) {
console.log('Request timed out — retry or increase timeout in client options');
}
}

NetworkError

Thrown when the request fails due to a network issue (no connection, DNS failure, etc.).

class NetworkError extends MemsolusError {}

Automatic retry

The SDK automatically retries requests that fail with 503 (service unavailable) by default. Configure retry behavior when initializing the client:

const client = new MemsolusClient({
apiKey: process.env.MEMSOLUS_API_KEY,
workspaceId: process.env.MEMSOLUS_WORKSPACE_ID,
retry: {
maxAttempts: 3, // maximum retry attempts (default 3)
backoffMs: 1000, // milliseconds between retries (default 1000)
retryOn: [503], // HTTP status codes that trigger retry
},
});

Retries use linear backoff: if backoffMs is 1000, the delays are 1s, 2s, 3s. To disable retries entirely, set maxAttempts: 1.


Complete error handling example

import {
MemsolusClient,
MemsolusError,
NotFoundError,
ValidationError,
QuotaExceededError,
UnauthorizedError,
ForbiddenError,
TimeoutError,
NetworkError,
} from '@memsolus/sdk';

const client = new MemsolusClient({
apiKey: process.env.MEMSOLUS_API_KEY,
workspaceId: process.env.MEMSOLUS_WORKSPACE_ID,
retry: {
maxAttempts: 3,
backoffMs: 1000,
retryOn: [503],
},
});

async function storeMemory(content: string, userId: string): Promise<string | null> {
try {
const memory = await client.memories.create({
content,
userId,
priority: 'MEDIUM',
});
return memory.id;
} catch (error) {
if (error instanceof UnauthorizedError) {
// API key problem — do not retry, escalate
throw new Error('Memsolus API key is invalid. Check your configuration.');
}

if (error instanceof ForbiddenError) {
// Permission problem — do not retry, escalate
throw new Error('API key does not have memory.write permission.');
}

if (error instanceof ValidationError) {
// Bad input — fix the payload, do not retry
console.error('Invalid memory payload:', error.message, error.code);
return null;
}

if (error instanceof QuotaExceededError) {
// Plan limit reached — notify the user
console.warn(
`Memory quota reached: ${error.used}/${error.limit} ${error.resource} used`
);
return null;
}

if (error instanceof TimeoutError || error instanceof NetworkError) {
// Transient infrastructure issue
console.error('Network or timeout error:', error.message);
return null;
}

if (error instanceof MemsolusError) {
// Unexpected SDK error
console.error(`Unexpected SDK error [${error.statusCode}]:`, error.message);
return null;
}

// Non-SDK error — re-throw
throw error;
}
}