mastra-ai/mastra · error · Error

Gateway API error ${res.status}: ${body}

Error message

Gateway API error ${res.status}: ${body}

What it means

The gateway-memory-client request() helper performs fetch calls against the Mastra Gateway memory API and throws a plain Error (`Gateway API error ${res.status}: ${body}`) whenever the response is not ok, embedding the HTTP status and the raw response body. It is a transport-level guard: any 4xx/5xx from the gateway (auth failures, missing threads, gateway downtime) is surfaced uniformly to the listThreads/getThread/createThread/updateThread/deleteThread/listMessages callers. The error is not typed per status, so callers must parse the message to branch.

Source

Thrown at packages/server/src/server/handlers/gateway-memory-client.ts:98

  private async request<T>(path: string, options: RequestInit = {}): Promise<T> {
    const url = `${this.baseUrl}${path}`;
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 10_000);
    try {
      const res = await fetch(url, {
        ...options,
        signal: options.signal ?? controller.signal,
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${this.apiKey}`,
          ...((options.headers as Record<string, string>) || {}),
        },
      });

      if (!res.ok) {
        const body = await res.text().catch(() => '');
        throw new Error(`Gateway API error ${res.status}: ${body}`);
      }

      return res.json() as Promise<T>;
    } finally {
      clearTimeout(timeout);
    }
  }

  // ── Threads ──────────────────────────────────────────────────

  async listThreads(params: {
    resourceId?: string;
    limit?: number;
    offset?: number;
  }): Promise<{ threads: GatewayThread[]; total: number }> {
    const query = new URLSearchParams();
    if (params.resourceId) query.set('resourceId', params.resourceId);
    if (params.limit != null) query.set('limit', String(params.limit));

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Parse the status from the message (regex on 'Gateway API error <status>') and branch: 401/403 fix auth, 404 verify the resource ID, 5xx retry with backoff.
  2. Verify the gateway base URL and that the gateway service is running and reachable at that URL.
  3. Check the gateway server logs for the corresponding request; the body in the message usually contains the upstream error detail.
  4. Confirm client/server versions are compatible (matching mastra versions) so the memory API routes exist.

Example fix

// before: treating all gateway failures the same
try { await client.listThreads(); } catch { alert('failed'); }
// after: branch on the embedded status and retry transient failures
try {
  await client.listThreads();
} catch (e) {
  const m = /Gateway API error (\d+)/.exec(e.message);
  const status = m ? Number(m[1]) : 0;
  if (status >= 500 || status === 429) return retryWithBackoff(() => client.listThreads());
  throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// health-check the gateway before issuing memory calls
const health = await fetch(`${gatewayBaseUrl}/health`);
if (!health.ok) throw new Error(`Gateway unreachable: ${health.status}`);

Type guard

function isGatewayApiError(e: unknown): e is Error & { status?: number } {
  if (!(e instanceof Error)) return false;
  const m = /Gateway API error (\d+)/.exec(e.message);
  if (m) (e as any).status = Number(m[1]);
  return !!m;
}

Try / catch

try {
  const threads = await memoryClient.listThreads();
} catch (e) {
  if (isGatewayApiError(e)) {
    const status = (e as any).status;
    if (status === 401 || status === 403) return reauthenticateAndRetry();
    if (status === 404) return handleMissingResource(e);
    if (status >= 500 || status === 429) return retryWithBackoff(() => memoryClient.listThreads());
  }
  throw e;
}

Prevention

When it happens

Trigger: Any memory client operation (listThreads, getThread, createThread, updateThread, deleteThread, listMessages) where the gateway responds with a non-ok status, e.g. 401 bad API key, 404 unknown thread/resource ID, 429 rate limit, 5xx gateway failure; also when the response body cannot be read (body defaults to empty string).

Common situations: Expired or wrong gateway credentials; client and gateway version mismatch so an endpoint route no longer exists (404); gateway behind a proxy returning 502/503 during deploys; requesting a thread ID that was deleted from another session.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/a89edc0170f78d98. Report an issue: GitHub.