mastra-ai/mastra · error

await extractError(res)

Error message

await extractError(res)

What it means

The factory-ui API client's `request` helper throws a generic Error whose message is whatever the server returned in the error response body (extracted by `extractError`). It is a catch-all for any non-OK HTTP response from the Factory backend (PUT/GET/POST), so the actual cause is the server-side message.

Source

Thrown at mastracode/factory-ui/src/api/client.ts:53

    // Non-JSON body — fall through to the status-based message.
  }
  return `Request failed (${res.status})`;
}

export function createApiClient({ baseUrl, fetchImpl }: ApiClientConfig): ApiClient {
  const doFetch = fetchImpl ?? globalThis.fetch;

  async function request<T>(method: string, path: string, body?: unknown): Promise<T> {
    // `credentials: 'include'` so cross-site session cookies are sent when the
    // SPA is hosted on a different origin than the API (platform deploy). It is
    // a no-op for same-origin local dev.
    const init: RequestInit = { method, credentials: 'include' };
    if (body !== undefined) {
      init.headers = { 'Content-Type': 'application/json' };
      init.body = JSON.stringify(body);
    }
    const res = await doFetch(`${baseUrl}${path}`, init);
    if (!res.ok) throw new Error(await extractError(res));
    return (await res.json()) as T;
  }

  return {
    get: <T>(path: string) => request<T>('GET', path),
    put: <T>(path: string, body?: unknown) => request<T>('PUT', path, body),
    post: <T>(path: string, body?: unknown) => request<T>('POST', path, body),
    del: <T>(path: string, body?: unknown) => request<T>('DELETE', path, body),
  };
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read the thrown message — it is the server's error text; fix the underlying server-reported cause
  2. Check authentication: ensure the session cookie is valid and you are logged in (401/403)
  3. Verify UI and server versions match (404/405 on newer/older routes)
  4. Inspect server logs for the corresponding 5xx if the message is generic

Example fix

// before
const res = await doFetch(`${baseUrl}${path}`, init);
if (!res.ok) throw new Error(await extractError(res));
// after (caller-side)
try {
  await client.put('/factory/settings', body);
} catch (e) {
  if (e instanceof Error && /401|unauthor/i.test(e.message)) await reauthenticate();
  else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: check the endpoint is reachable and authenticated
const probe = await fetch(`${baseUrl}/health`, { credentials: 'include' });
if (!probe.ok) throw new Error(`Factory API unavailable (${probe.status}); ${probe.status === 401 ? 're-authenticate' : 'check server'}`);

Try / catch

try {
  await client.put('/factory/project', body);
} catch (e) {
  if (e instanceof Error) {
    if (/401|403|unauthor|forbidden/i.test(e.message)) await reauthenticate();
    else if (/404/i.test(e.message)) console.error('Route mismatch: check UI/server versions');
    else throw e; // surface server message (it is extractError output)
  }
}

Prevention

When it happens

Trigger: Any `client.get/put/...` call where `doFetch` resolves with `res.ok === false` (4xx/5xx); the thrown message is the response body text from `extractError(res)`.

Common situations: Session expired (401/403) with credentials: 'include' cookie rejected; server 500 during a factory operation; route not found after version mismatch between UI and server; CSRF/cookie issues in embedded contexts.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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