mastra-ai/mastra · error · PlatformApiError

Failed to read database status — ${await extractError(res)}

Error message

Failed to read database status — ${await extractError(res)}

What it means

getDatabaseStatus polls GET /v1/server/projects/:projectId/databases/:databaseId to check Neon provisioning progress. A non-ok response aborts the polling loop immediately with this PlatformApiError containing the upstream status and server error text.

Source

Thrown at mastracode/mastra-factory/src/platform.ts:175

export async function getDatabaseStatus({
  token,
  orgId,
  projectId,
  databaseId,
  signal,
}: {
  token: string;
  orgId: string;
  projectId: string;
  databaseId: string;
  signal?: AbortSignal;
}): Promise<AttachedDatabase> {
  const res = await platformFetch(
    `${MASTRA_PLATFORM_API_URL}/v1/server/projects/${encodeURIComponent(projectId)}/databases/${encodeURIComponent(databaseId)}`,
    { headers: authHeaders(token, orgId), signal },
  );
  if (!res.ok) {
    throw new PlatformApiError(res.status, `Failed to read database status — ${await extractError(res)}`);
  }
  const body = (await res.json()) as { database: AttachedDatabase };
  return body.database;
}

/** GET /v1/server/projects/:id/databases/:dbId/connection — only 200s when `ready`. */
export async function getDatabaseConnection({
  token,
  orgId,
  projectId,
  databaseId,
}: {
  token: string;
  orgId: string;
  projectId: string;
  databaseId: string;
}): Promise<DatabaseConnection> {
  const res = await platformFetch(

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the status after the em-dash: re-login on 401, verify ids on 404, back off on 429.
  2. Confirm the database still exists in the platform dashboard and rerun if it was deleted.
  3. Reduce polling frequency (increase intervalMs in waitForDatabaseReady) if rate-limited.
  4. Retry the whole provisioning flow after transient 5xx errors.

Example fix

// before
const db = await waitForDatabaseReady({ token, orgId, projectId, databaseId });
// after
const db = await waitForDatabaseReady({ token, orgId, projectId, databaseId, intervalMs: 3000 }); // slower poll avoids 429
Defensive patterns

Strategy: retry

Validate before calling

// verify ids are non-empty before polling
if (!projectId || !databaseId) throw new Error('projectId and databaseId are required for status polling');

Try / catch

try {
  const db = await waitForDatabaseReady({ token, orgId, projectId, databaseId });
} catch (err) {
  if (err instanceof PlatformApiError && (err.status === 401 || err.status === 429)) {
    await refreshAuth(); await sleep(3000);
    return waitForDatabaseReady({ token, orgId, projectId, databaseId, intervalMs: 5000 });
  }
  throw err;
}

Prevention

When it happens

Trigger: The status poll returns 401 (token expired during the wait), 403, 404 (database or project id wrong/deleted), 429 (polling too fast), or 5xx — from inside waitForDatabaseReady's loop.

Common situations: Long-running provisioning where the token expires mid-poll; database deleted by a teammate while waiting; wrong project/database ids after a re-run; aggressive polling tripping rate limits.

Related errors


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