windmill-labs/windmill · error
Timed out waiting for the project to become reachable
Error message
Timed out waiting for the project to become reachable
What it means
waitUntilSupabaseHealthy polls the Supabase projects list until the newly created project reports status ACTIVE_HEALTHY. If the loop exhausts its attempts before the project becomes reachable, it throws this timeout error. Newly created Supabase projects usually take a few minutes to provision, so this fires when provisioning is slower than the wait budget or the project failed to start.
Source
Thrown at frontend/src/lib/components/workspaceSettings/supabaseProvisioning.ts:177
onStatus?: (status: string | undefined) => void,
attempts = 60
): Promise<SupabaseProject> {
for (let i = 0; i < attempts; i++) {
await new Promise((r) => setTimeout(r, 5000))
let list: SupabaseProject[]
try {
list = await listSupabaseProjects(token)
} catch (err) {
// A transient failure is worth another poll; an expired token is not -- retrying it
// burns five minutes and then reports a timeout, which names the wrong problem.
if (!get(oauthStore)?.access_token) throw err
continue
}
const project = list?.find?.((p) => projectRef(p) === projectId)
if (project?.status === 'ACTIVE_HEALTHY') return project
onStatus?.(project?.status)
}
throw new Error('Timed out waiting for the project to become reachable')
}
/**
* The session-mode Supavisor endpoint of the project's primary database.
*
* Which pooler a project sits behind is assigned by Supabase, not derived from its
* region: constructing `aws-0-<region>.pooler.supabase.com` is wrong for every project
* that landed on another one, and the resulting resource never connects.
*/
export async function getSupabasePooler(token: string, projectId: string): Promise<SupabasePooler> {
const res = await fetch(`${base}/api/oauth/get_supabase_pooler/${projectId}`, {
headers: headers(token)
})
const configs: SupabasePooler[] = await unwrap(res, 'Could not read the connection details')
const primary = configs.filter((c) => c.database_type === 'PRIMARY')
const pooler = primary.find((c) => c.pool_mode === 'session') ?? primary[0] ?? configs[0]
if (!pooler) throw new Error('Supabase returned no connection details for this project')
return poolerView on GitHub (pinned to e474e8803c)
Solutions
- Wait a few minutes and re-run the setup/provisioning step — the project usually becomes ACTIVE_HEALTHY on its own.
- Check the project's status in the Supabase dashboard; if it's failed/stuck, delete it and create a new one.
- Verify the projectId being polled matches the project returned by the create call.
- Increase the polling timeout/attempts in supabaseProvisioning.ts if provisioning in your region is consistently slow.
Defensive patterns
Strategy: retry
Validate before calling
const project = (await listSupabaseProjects(token)).find((p) => p.id === projectId)
if (project && project.status !== 'ACTIVE_HEALTHY') console.log('still', project.status, '- keep waiting') Type guard
function isHealthy(p?: { status?: string }): p is { status: 'ACTIVE_HEALTHY' } & Record<string, unknown> {
return !!p && p.status === 'ACTIVE_HEALTHY'
} Try / catch
try {
await waitUntilSupabaseHealthy(token, projectId, onStatus)
} catch (e) {
if (e.message.includes('Timed out')) {
// resume provisioning later; project may still be coming up
} else throw e
} Prevention
- Provision during off-peak hours; Supabase creation can be slow.
- Show live project status (onStatus) so users know provisioning is still in progress.
- Verify the created project ref matches the polled projectId before waiting.
When it happens
Trigger: runSetup creates a Supabase project and polls for health; the project stays in another status (e.g. 'COMING_UP', 'RESTORING') or disappears from the list for the whole polling window, then the timeout is thrown.
Common situations: Supabase provisioning backlogs making new projects take longer than the wait window; project stuck in an error state; wrong projectId being matched (created project ref doesn't match the one polled); heavy region with slow cold-start.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out waiting for flow ${id} to complete
- Timed out waiting for job ${id}
- Timed out waiting for job ${id} to complete
- Giving up polling job ${jobId} after ${MAX_CONSECUTIVE_POLL_
- Failed to poll dependencies job ${jobId}: ${e?.message ?? e}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/38bd14b4e2950973.
Report an issue: GitHub.