{"record":{"id":"604feec877f5a43e","repo":"mastra-ai/mastra","slug":"failed-to-read-database-status-await-extracter","errorCode":null,"errorMessage":"Failed to read database status — ${await extractError(res)}","messagePattern":"Failed to read database status — (.+?)","errorType":"http","errorClass":"PlatformApiError","httpStatus":null,"severity":"error","filePath":"mastracode/mastra-factory/src/platform.ts","lineNumber":175,"sourceCode":"export async function getDatabaseStatus({\n  token,\n  orgId,\n  projectId,\n  databaseId,\n  signal,\n}: {\n  token: string;\n  orgId: string;\n  projectId: string;\n  databaseId: string;\n  signal?: AbortSignal;\n}): Promise<AttachedDatabase> {\n  const res = await platformFetch(\n    `${MASTRA_PLATFORM_API_URL}/v1/server/projects/${encodeURIComponent(projectId)}/databases/${encodeURIComponent(databaseId)}`,\n    { headers: authHeaders(token, orgId), signal },\n  );\n  if (!res.ok) {\n    throw new PlatformApiError(res.status, `Failed to read database status — ${await extractError(res)}`);\n  }\n  const body = (await res.json()) as { database: AttachedDatabase };\n  return body.database;\n}\n\n/** GET /v1/server/projects/:id/databases/:dbId/connection — only 200s when `ready`. */\nexport async function getDatabaseConnection({\n  token,\n  orgId,\n  projectId,\n  databaseId,\n}: {\n  token: string;\n  orgId: string;\n  projectId: string;\n  databaseId: string;\n}): Promise<DatabaseConnection> {\n  const res = await platformFetch(","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/mastra-factory/src/platform.ts#L157-L193","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the status after the em-dash: re-login on 401, verify ids on 404, back off on 429.","Confirm the database still exists in the platform dashboard and rerun if it was deleted.","Reduce polling frequency (increase intervalMs in waitForDatabaseReady) if rate-limited.","Retry the whole provisioning flow after transient 5xx errors."],"exampleFix":"// before\nconst db = await waitForDatabaseReady({ token, orgId, projectId, databaseId });\n// after\nconst db = await waitForDatabaseReady({ token, orgId, projectId, databaseId, intervalMs: 3000 }); // slower poll avoids 429","handlingStrategy":"retry","validationCode":"// verify ids are non-empty before polling\nif (!projectId || !databaseId) throw new Error('projectId and databaseId are required for status polling');","typeGuard":null,"tryCatchPattern":"try {\n  const db = await waitForDatabaseReady({ token, orgId, projectId, databaseId });\n} catch (err) {\n  if (err instanceof PlatformApiError && (err.status === 401 || err.status === 429)) {\n    await refreshAuth(); await sleep(3000);\n    return waitForDatabaseReady({ token, orgId, projectId, databaseId, intervalMs: 5000 });\n  }\n  throw err;\n}","preventionTips":["Use a polling interval of a few seconds to avoid 429s.","Refresh the auth token if provisioning is expected to take many minutes.","Confirm the database/project still exist before and during polling.","Treat 4xx as terminal; retry only 429/5xx."],"tags":["http-error","platform-api","polling","network"],"backgroundTag":"http-api-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}