mastra-ai/mastra · error

Request failed (${response.status}) / server-provided messag

Error message

Request failed (${response.status}) / server-provided message

What it means

fetchFactoryDecisions/actOnFactoryDecision hit the factory decisions API and throwRequestError converts any non-OK HTTP response into a thrown Error. The message prefers the server-provided body message/error field and falls back to a generic 'Request failed (<status>)'. This surfaces backend rejection (auth, bad params, server error) to the UI layer.

Source

Thrown at mastracode/factory-ui/src/ui/domains/factory/services/decisions.ts:48

  createdAt: string;
  updatedAt: string;
  completedAt: string | null;
}

export interface FactoryDecisionPage {
  decisions: FactoryDecisionSummary[];
  nextCursor?: string;
}

async function throwRequestError(response: Response): Promise<never> {
  let message = `Request failed (${response.status})`;
  try {
    const body = (await response.json()) as { error?: string; message?: string };
    message = body.message ?? body.error ?? message;
  } catch {
    // Keep the status-based fallback for non-JSON responses.
  }
  throw new Error(message);
}

export async function fetchFactoryDecisions(
  baseUrl: string,
  githubProjectId: string,
  options: { statuses?: FactoryDecisionStatus[]; before?: string; limit?: number } = {},
): Promise<FactoryDecisionPage> {
  const query = new URLSearchParams();
  if (options.statuses?.length) query.set('statuses', options.statuses.join(','));
  if (options.before) query.set('before', options.before);
  if (options.limit) query.set('limit', String(options.limit));
  const suffix = query.size > 0 ? `?${query}` : '';
  const response = await fetch(
    `${baseUrl}/web/factory/projects/${encodeURIComponent(githubProjectId)}/decisions${suffix}`,
    { headers: { Accept: 'application/json' }, credentials: 'include' },
  );
  if (!response.ok) return throwRequestError(response);
  return (await response.json()) as FactoryDecisionPage;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Inspect error.message: if it contains the server message, fix the request it describes; otherwise check response status via a network tab
  2. Verify the user session/auth cookie is valid for the factory baseUrl
  3. Validate statuses/before/limit values against the current FactoryDecisionStatus enum and API limits
  4. Retry after confirming the factory backend is healthy if status is 5xx

Example fix

// before
const decisions = await fetchFactoryDecisions(baseUrl, projectId, { statuses: ['unknown-status'] });
// after
const decisions = await fetchFactoryDecisions(baseUrl, projectId, { statuses: ['pending'] satisfies FactoryDecisionStatus[] });
Defensive patterns

Strategy: try-catch

Validate before calling

const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
if (!isNonEmptyString(baseUrl) || !isNonEmptyString(githubProjectId)) throw new Error('baseUrl and githubProjectId are required');
const validStatuses = new Set<string>(['pending', 'approved', 'rejected']); // keep in sync with FactoryDecisionStatus
if (options.statuses && !options.statuses.every(s => validStatuses.has(s))) throw new Error('Invalid status filter');

Type guard

function isFactoryDecisionStatus(v: unknown): v is FactoryDecisionStatus {
  return typeof v === 'string' && ['pending', 'approved', 'rejected'].includes(v);
}

Try / catch

try {
  const decisions = await fetchFactoryDecisions(baseUrl, githubProjectId, { statuses });
} catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (/401|403/.test(msg)) showLoginPrompt();
  else if (/5\d\d/.test(msg)) retryLater();
  else showError(msg);
}

Prevention

When it happens

Trigger: Any response with response.ok === false from GET factory decisions (with statuses/before/limit query params) or POST/PATCH actOnFactoryDecision, including 401/403 auth failures, invalid githubProjectId, bad query params (limit out of range, malformed before cursor), or 5xx server errors.

Common situations: Expired or missing session cookie (credentials), requesting decisions with a status enum value the server no longer accepts after a version change, paginating past the last page with an invalid 'before' cursor, or the factory server being down (502/503).

Related errors


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