{"record":{"id":"a94d476cd7ae1035","repo":"mastra-ai/mastra","slug":"request-failed-res-status-server-provided-m","errorCode":null,"errorMessage":"Request failed (${res.status}) / server-provided message","messagePattern":"Request failed \\((.+?)\\) / server-provided message","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory-ui/src/ui/domains/factory/services/audit.ts","lineNumber":102,"sourceCode":"    'actors' in value &&\n    typeof value.actors === 'object' &&\n    value.actors !== null &&\n    !Array.isArray(value.actors) &&\n    Object.values(value.actors).every(isAuditActorProfile) &&\n    (!('nextCursor' in value) || isOptionalString(value.nextCursor))\n  );\n}\n\nasync function throwRequestError(res: Response): Promise<never> {\n  let message = `Request failed (${res.status})`;\n  try {\n    const body: unknown = await res.json();\n    if (typeof body === 'object' && body !== null) {\n      if ('message' in body && typeof body.message === 'string') message = body.message;\n      else if ('error' in body && typeof body.error === 'string') message = body.error;\n    }\n  } catch {}\n  throw new Error(message);\n}\n\nexport async function fetchAuditEvents(\n  baseUrl: string,\n  factoryProjectId: string,\n  options: { actions?: string[]; actorIds?: string[]; before?: string; limit?: number; signal?: AbortSignal } = {},\n): Promise<AuditEventPage> {\n  const query = new URLSearchParams();\n  if (options.actions && options.actions.length > 0) query.set('actions', options.actions.join(','));\n  if (options.actorIds && options.actorIds.length > 0) query.set('actorIds', options.actorIds.join(','));\n  if (options.before) query.set('before', options.before);\n  if (options.limit) query.set('limit', String(options.limit));\n  const qs = query.size > 0 ? `?${query}` : '';\n  const res = await fetch(`${baseUrl}/web/factory/projects/${encodeURIComponent(factoryProjectId)}/audit${qs}`, {\n    headers: { Accept: 'application/json' },\n    credentials: 'include',\n    signal: options.signal,\n  });","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/ui/domains/factory/services/audit.ts#L84-L120","documentation":"throwRequestError in audit.ts converts a non-OK HTTP response into an Error. It prefers a server-provided message or error string from the JSON body and otherwise falls back to 'Request failed (<status>).'. fetchAuditEvents and fetchAuditPortalLink delegate all HTTP failures to it.","triggerScenarios":"Any non-ok response from the audit endpoints — 401/403 unauthenticated or unauthorized user, 404 unknown project, 429 rate limit, 5xx server error — where the body either carries {message}|{error} or is non-JSON (triggering the fallback text).","commonSituations":"Session cookie expired during an audit-log page load; user lacks audit-view permission; HTML login page returned by an auth gateway (hence the fallback); transient 502 from the API.","solutions":["Read the thrown message: a server body message names the real problem; 'Request failed (N)' means inspect status N.","For 401, re-authenticate; for 403, grant the actor audit read permission.","For 5xx/429, retry with backoff and check server/gateway logs.","Confirm the baseUrl points at the API returning JSON, not an HTML-serving proxy."],"exampleFix":"// before\nclass AuditError extends Error { constructor(public status: number, m: string){super(m);} }\n// after\nclass AuditError extends Error {\n  constructor(public status: number, m: string){ super(m); }\n}\nthrow new AuditError(res.status, message); // callers can branch on status, e.g. 401 -> re-login","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isAuditHttpError(e: unknown): e is Error & { status?: number } {\n  return e instanceof Error && typeof (e as any).status === 'number';\n}","tryCatchPattern":"try {\n  const events = await fetchAuditEvents(baseUrl, projectId, { actions, actorIds });\n} catch (e) {\n  const status = (e as { status?: number }).status;\n  if (status === 401) redirectToLogin();\n  else if (status === 403) showNoPermission();\n  else showToast(e instanceof Error ? e.message : 'Failed to load audit events');\n}","preventionTips":["Attach the HTTP status to thrown errors so callers can branch reliably.","Keep sessions fresh; re-authenticate before long audit sessions.","Verify audit read permissions for the actor.","Ensure the API returns JSON error bodies with { message }."],"tags":["http","audit","api-error","auth"],"backgroundTag":"request-failed-status","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}