windmill-labs/windmill · error

Supabase returned no connection details for this project

Error message

Supabase returned no connection details for this project

What it means

getSupabasePooler fetches the project's pooler connection configs from the Windmill backend (`/api/oauth/get_supabase_pooler/<projectId>`) and picks the PRIMARY session-mode pooler. If the response contains an empty list (no configs at all), it throws 'Supabase returned no connection details for this project'. This means Supabase (via the backend proxy) returned no usable database endpoints for the project.

Source

Thrown at frontend/src/lib/components/workspaceSettings/supabaseProvisioning.ts:194

	}
	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 pooler
}

export type SupabaseConnection = {
	mode: SupabaseConnectionMode
	pooler?: SupabasePooler
	/** Why session pooling was asked for and not used. Absent when nothing was given up. */
	unavailable?: string
}

/**
 * The endpoint a project should be reached through, degrading rather than failing. Reading the
 * pooler config needs the `database_pooling_config_read` scope, which an instance's OAuth app
 * may not have. A direct connection still works where the workers have IPv6, so fall back to
 * it and say so.
 */
export async function resolveSupabaseConnection(
	token: string,

View on GitHub (pinned to e474e8803c)

Solutions

  1. Retry a minute later — fresh projects may not have pooler details published yet.
  2. Confirm the project is ACTIVE_HEALTHY and not paused in the Supabase dashboard.
  3. Verify the backend's Supabase Management API integration still matches the current pooler config response shape (database_type, pool_mode).
  4. Check the project ID passed to get_supabase_pooler is the correct Supabase ref.
Defensive patterns

Strategy: validation

Validate before calling

const configs = await getSupabasePoolerConfigs(token, projectId) // raw fetch
if (!Array.isArray(configs) || configs.length === 0) {
  throw new Error('project has no pooler configs yet — retry after ACTIVE_HEALTHY')
}

Type guard

function hasPooler(c: SupabasePooler[] | undefined): c is [SupabasePooler, ...SupabasePooler[]] {
  return Array.isArray(c) && c.length > 0
}

Try / catch

try {
  const conn = await resolveSupabaseConnection(token, projectId)
} catch (e) {
  if (e.message.includes('no connection details')) await waitUntilSupabaseHealthy(token, projectId)
  else throw e
}

Prevention

When it happens

Trigger: resolveSupabaseConnection calls getSupabasePooler for a project whose configs endpoint returns an empty array — typically a brand-new project whose database endpoints aren't published yet, or a project where pooler info is unavailable.

Common situations: Calling resolveSupabaseConnection immediately after project creation before Supabase publishes pooler configs; project paused/deleted; Supabase changed the pooler config payload shape (database_type/pool_mode fields) so filtering empties the list.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/10493559bea80d4f. Report an issue: GitHub.