mastra-ai/mastra · error · Error

detail

Error message

detail

What it means

When the platform API returns a non-401 error and the response body includes an error detail (e.g. an RFC 7807 `detail` field), throwApiError rethrows that server-provided detail string verbatim as the Error message. The developer sees the server's own explanation of why the request failed.

Source

Thrown at packages/cli/src/commands/auth/client.ts:43

  if (MASTRA_PLATFORM_API_URL.includes('staging')) return 'https://studio.staging.mastra.ai';
  return 'https://studio.mastra.ai';
}

export const MASTRA_STUDIO_URL = deriveStudioUrl();

export const SESSION_EXPIRED_MESSAGE = 'Session expired. Run: mastra auth login';

/**
 * Throw a standardized error for API failures.
 * - 401: "Session expired" (authentication failed)
 * - Other: Show the server's error detail or fall back to status code
 */
export function throwApiError(message: string, status: number, detail?: string): never {
  if (status === 401) {
    throw new Error(SESSION_EXPIRED_MESSAGE);
  }
  if (detail) {
    throw new Error(detail);
  }
  throw new Error(`${message}: ${status}`);
}

/** Best-effort message from platform JSON error bodies (RFC 7807 `detail`, etc.). */
export function extractApiErrorDetail(error: unknown): string | undefined {
  if (!error || typeof error !== 'object') return undefined;
  const o = error as Record<string, unknown>;

  let detail: string | undefined;
  if (typeof o.detail === 'string' && o.detail.trim()) detail = o.detail;
  else if (typeof o.message === 'string' && o.message.trim()) detail = o.message;
  else if (typeof o.error === 'string' && o.error.trim()) detail = o.error;

  // Validation errors (400) carry the useful part in errors[] — field name plus
  // message (e.g. the valid-options enum for a bad --region). Without this the
  // user only sees "The request body contains invalid fields".
  const fieldErrors = Array.isArray(o.errors)

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read the detail message — it comes directly from the Mastra platform and names the failing constraint.
  2. Fix the request inputs the detail points to (token id, org id, payload fields).
  3. Retry after fixing; if detail is a 5xx artifact, retry later or check platform status.
Defensive patterns

Strategy: try-catch

Type guard

function isServerDetailError(err: unknown): err is Error {
  return err instanceof Error && !err.message.startsWith('Session expired');
}

Try / catch

try {
  await createToken(token, name);
} catch (err) {
  if (err instanceof Error) {
    // message is the server-provided detail; surface it to the user verbatim
    console.error(`Request rejected by platform: ${err.message}`);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: fetchOrgs, createToken, listTokensAction, revokeTokenAction, or fetchProjects receives a non-401 HTTP error (400/403/404/409/500) whose JSON body carries a detail/description field; that raw detail string becomes the thrown message.

Common situations: Revoking a token that does not exist (404), creating a token with an invalid name (400), lacking org permissions (403), platform 5xx with a structured error body.

Related errors


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