# How Supermemory Handles Errors: Typed Classes, Centralized Wrappers, and Consistent HTTP Responses

> Discover how Supermemory manages errors with typed classes, centralized wrappers, and consistent HTTP responses across its Raycast extension, browser extension, and Next.js backend.

- Repository: [supermemory/supermemory](https://github.com/supermemoryai/supermemory)
- Tags: best-practices
- Published: 2026-03-25

---

**Supermemory implements a layered error-handling strategy using typed error classes, centralized request wrappers, and consistent HTTP response patterns across its Raycast extension, browser extension, and Next.js backend.**

Error handling in modern full-stack applications requires discipline across multiple runtimes and clients. In the `supermemoryai/supermemory` repository, the development team established a robust error management architecture that spans TypeScript frontend clients, Next.js API routes, and external service integrations. This article examines how Supermemory handles errors through typed abstractions, centralized request logic, and consistent JSON contracts that enable reliable debugging and user feedback.

## Typed Error Classes for Type-Safe Discrimination

Supermemory defines **custom error classes** that extend the native `Error` object to enable precise `instanceof` checking at runtime. These classes are distributed across client applications to provide context-specific error information.

In [`apps/raycast-extension/src/api.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/raycast-extension/src/api.ts) (lines 56‑63), the `SupermemoryAPIError` class captures HTTP status codes and response messages:

```typescript
class SupermemoryAPIError extends Error {
  constructor(
    message: string,
    public status: number
  ) {
    super(message);
    this.name = "SupermemoryAPIError";
  }
}

```

The same file defines `AuthenticationError` (lines 66‑70) to specifically signal invalid or missing API keys. Meanwhile, the browser extension uses a base `ExtensionError` class defined in [`apps/browser-extension/utils/types.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/browser-extension/utils/types.ts) (line 119), which `SupermemoryAPIError` extends (line 137) for extension-specific contexts.

This hierarchy allows client code to distinguish between **authentication failures**, **API-level errors**, and **generic runtime exceptions** without parsing error strings.

## Centralized Request Wrappers in the Raycast Extension

All HTTP calls from the Raycast extension flow through a single `makeAuthenticatedRequest` function in [`apps/raycast-extension/src/api.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/raycast-extension/src/api.ts) (lines 78‑135). This wrapper implements a consistent error-handling pipeline:

1. **Injects the Authorization header** (`Bearer <apiKey>`) for authenticated endpoints.
2. **Validates the response status** via `response.ok` and extracts detailed messages from JSON error bodies when available.
3. **Throws typed errors**: `AuthenticationError` for 401 responses and `SupermemoryAPIError` for other non-2xx statuses.
4. **Catches network-level exceptions** and re-throws them as `SupermemoryAPIError` instances with a "Network error" prefix.

This centralization ensures that every API call benefits from identical error transformation logic, preventing inconsistent error handling across different features.

## Next.js API Route Error Patterns

Serverless routes in `apps/web/app/api/` follow a standardized try/catch pattern that combines **structured logging** with **HTTP-appropriate status codes**.

### Generic Internal Server Errors

The onboarding research endpoint in [`apps/web/app/api/onboarding/research/route.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/app/api/onboarding/research/route.ts) (lines 70‑73) catches unexpected failures and returns a generic 500 response:

```typescript
try {
  // ...logic...
} catch (error) {
  console.error("Research error:", error);
  return Response.json(
    { error: "Internal server error" },
    { status: 500 }
  );
}

```

### Input Validation and External Service Errors

The OG metadata scraper in [`apps/web/app/api/og/route.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/app/api/og/route.ts) implements granular status code selection:
- Returns **400 Bad Request** for malformed URLs (lines 42‑57).
- Returns **500 Internal Server Error** for unexpected fetch failures (lines 71‑77, 92‑98).

Similarly, the content extraction route in [`apps/web/app/api/onboarding/extract-content/route.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/app/api/onboarding/extract-content/route.ts) returns **400** for malformed payloads (lines 16‑28) and **500** for downstream API failures (lines 43‑60), logging each error context for debugging.

## Middleware-Level Authentication Guards

The Next.js middleware in [`apps/web/middleware.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/middleware.ts) (lines 21‑30) provides **early error termination** for unauthenticated API requests. If a request path starts with `/api/` and no session cookie is present, the middleware immediately returns:

```json
{ "error": "Unauthorized" }

```

With an HTTP **401 Unauthorized** status. This prevents unauthenticated traffic from reaching application logic, reducing unnecessary server load and potential security exposure.

## Library-Level Logging and Observability

Low-level utilities in `packages/tools/` catch internal errors, log structured metadata, and re-throw wrapped errors that bubble up to route handlers. In [`packages/tools/src/openai/tools.ts`](https://github.com/supermemoryai/supermemory/blob/main/packages/tools/src/openai/tools.ts) (lines 270‑306), the error handler uses a shared logger:

```typescript
catch (error) {
  logger.error("Error generating response", {
    error: error instanceof Error ? error.message : "Unknown error",
  });
  throw new Error(`Supermemory API request failed: ${error}`);
}

```

The Vercel middleware in [`packages/tools/src/vercel/middleware.ts`](https://github.com/supermemoryai/supermemory/blob/main/packages/tools/src/vercel/middleware.ts) (lines 152‑158) follows an identical pattern. These logs feed into **Sentry**, configured in [`apps/web/next.config.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/next.config.ts), enabling production monitoring of uncaught exceptions and downstream service failures.

## Consistent Error Response Contracts

All JSON error responses across the Supermemory ecosystem share a uniform shape:

```json
{ "error": "<human-readable message>" }

```

This contract allows the Raycast extension, browser extension, and web UI to parse error responses without implementing custom parsers for each endpoint. Clients can reliably extract user-facing messages from the `error` property regardless of whether the failure originated from input validation, authentication, or internal server errors.

## Practical Implementation: Handling Errors in the Raycast Client

When consuming the Supermemory API from the Raycast extension, developers leverage the typed error classes for precise user feedback:

```typescript
import { fetchProjects, addMemory, SupermemoryAPIError, AuthenticationError } from "./api";

async function listProjects() {
  try {
    const projects = await fetchProjects();
    console.log("Projects:", projects);
  } catch (err) {
    if (err instanceof SupermemoryAPIError) {
      console.error(`API error (${err.status}): ${err.message}`);
      // Display status-specific UI feedback
    } else if (err instanceof AuthenticationError) {
      console.error("Invalid API key:", err.message);
      // Prompt user to update credentials
    } else {
      console.error("Unexpected error:", err);
      // Generic error fallback
    }
  }
}

async function createMemory() {
  try {
    const memory = await addMemory({
      content: "Important note from meeting",
      title: "Meeting notes",
    });
    console.log("Memory added:", memory.id);
  } catch (err) {
    console.error(err instanceof Error ? err.message : "Unknown error");
  }
}

```

This pattern enables UI components to display **contextual error messages**—such as "Invalid API key" versus "Network error"—based on the specific error type caught.

## Summary

- **Typed error classes** (`SupermemoryAPIError`, `AuthenticationError`, `ExtensionError`) enable type-safe error discrimination via `instanceof` checks.
- **Centralized request wrappers** in [`apps/raycast-extension/src/api.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/raycast-extension/src/api.ts) ensure consistent header injection, status validation, and error transformation.
- **Next.js API routes** return specific HTTP status codes (400 for validation, 401 for authentication, 500 for server errors) with consistent JSON bodies.
- **Middleware guards** in [`apps/web/middleware.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/middleware.ts) block unauthenticated requests early with 401 responses.
- **Library-level logging** in `packages/tools/` captures detailed error context for Sentry monitoring while propagating clean error messages to callers.
- **Uniform error contracts** (`{ "error": "message" }`) simplify client-side error parsing across all Supermemory applications.

## Frequently Asked Questions

### What specific error classes does Supermemory define for API failures?

Supermemory defines `SupermemoryAPIError` (for general HTTP errors with status codes) and `AuthenticationError` (for invalid API keys) in [`apps/raycast-extension/src/api.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/raycast-extension/src/api.ts). The browser extension additionally uses an `ExtensionError` base class defined in [`apps/browser-extension/utils/types.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/browser-extension/utils/types.ts) to create hierarchical error types specific to extension contexts.

### How does Supermemory distinguish between authentication and network errors?

The `makeAuthenticatedRequest` function in [`apps/raycast-extension/src/api.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/raycast-extension/src/api.ts) checks the HTTP status code: it throws `AuthenticationError` for 401 responses and `SupermemoryAPIError` for other non-2xx statuses. Network-level exceptions (fetch failures) are caught and re-thrown as `SupermemoryAPIError` instances with a "Network error" prefix, allowing callers to handle connectivity issues separately from credential problems.

### What HTTP status codes does Supermemory return for different error scenarios?

Supermemory returns **400 Bad Request** for malformed input (e.g., invalid URLs in the OG scraper), **401 Unauthorized** for missing or invalid authentication (from middleware or API routes), and **500 Internal Server Error** for unexpected runtime failures or downstream service errors. This mapping is implemented consistently across routes like [`apps/web/app/api/og/route.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/app/api/og/route.ts) and [`apps/web/app/api/onboarding/extract-content/route.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/app/api/onboarding/extract-content/route.ts).

### How does Supermemory monitor production errors?

Supermemory integrates **Sentry** via [`apps/web/next.config.ts`](https://github.com/supermemoryai/supermemory/blob/main/apps/web/next.config.ts) to capture uncaught exceptions. Additionally, library code in [`packages/tools/src/openai/tools.ts`](https://github.com/supermemoryai/supermemory/blob/main/packages/tools/src/openai/tools.ts) and [`packages/tools/src/vercel/middleware.ts`](https://github.com/supermemoryai/supermemory/blob/main/packages/tools/src/vercel/middleware.ts) uses a shared logger to record error details before re-throwing, ensuring that both handled and unhandled errors are observable in production environments.