connect ENETUNREACH 2600:1f1c:…:5432
What it means
ENETUNREACH ("network is unreachable") on a 2600:1f1c:… address means your client resolved the direct db.<ref>.supabase.co host to its IPv6 address but has no IPv6 route. The direct host is IPv6-only; IPv4-only CI runners, serverless functions, and Edge runtimes can't reach it. Connect through the Supavisor pooler host instead, which is IPv4-compatible.
Why it happens
connect ENETUNREACH 2600:1f1c:…:5432 is an operating-system network error (ENETUNREACH = "network is unreachable"), not a Postgres error. The client resolved a hostname to an IPv6 address in the 2600:1f1c:… block and then had no route to send packets to it.
On Supabase this is almost always the direct database host:
- The direct host is IPv6-only.
db.<project-ref>.supabase.copublishes anAAAA(IPv6) record and no publicA(IPv4) record. If your client only has IPv4 connectivity, the address is unroutable and the socket fails immediately withENETUNREACH. - Your runtime is IPv4-only. Many GitHub Actions/CI runners, serverless platforms (Lambda, Vercel functions), and Edge runtimes have no IPv6 route. They resolve the
AAAArecord, try to connect, and can't. - You hardcoded the direct host in a connection string. Older Supabase docs and copied
.envfiles often usedb.<ref>.supabase.co:5432. That endpoint only works from IPv6-capable networks.
The fix is not to force IPv4 on the direct host — there isn't a public one. Use the pooler.
How to fix it
First, confirm the cause. The direct host should return an IPv6 (AAAA) record and no IPv4 (A) record:
# IPv6 record exists (this is what your client tried to reach)
dig +short AAAA db.<project-ref>.supabase.co
# 2600:1f1c:...
# No public IPv4 record on the direct host
dig +short A db.<project-ref>.supabase.co
# (empty)
Now check the pooler host — it resolves to a routable IPv4 address:
dig +short A aws-0-<region>.pooler.supabase.com
# e.g. 52.x.x.x (routable from IPv4-only runners)
Switch your connection to the Supavisor pooler. The hostname, username, and port all change:
# Before (IPv6-only, fails on IPv4-only clients)
postgresql://postgres:[password]@db.<project-ref>.supabase.co:5432/postgres
# After — transaction mode (port 6543), IPv4-compatible
postgresql://postgres.<project-ref>:[password]@aws-0-<region>.pooler.supabase.com:6543/postgres
# After — session mode (port 5432)
postgresql://postgres.<project-ref>:[password]@aws-0-<region>.pooler.supabase.com:5432/postgres
Two changes people miss:
- The username becomes
postgres.<project-ref>(tenant-qualified), not plainpostgres. Getting this wrong yields password authentication failed. - The host and region come from your project's Database settings → Connection string → the "Session" / "Transaction" pooler tabs. Find your exact
<region>there; don't guess it.
Once connected through the pooler, confirm the socket is live:
select 1;
Grab your exact values (host, port, region, tenant-qualified user) with the connection string builder.
How to prevent it
- Default to the pooler host (
aws-0-<region>.pooler.supabase.com) for anything that runs off your own machine — CI, serverless, Edge, and migrations. Reserve the direct host for IPv6-capable environments only. - Store the pooler connection string in your CI/CD secrets from the start, with the
postgres.<project-ref>username, so no one copies the IPv6-only direct host into an IPv4-only runner. - Use transaction mode (6543) for short-lived migration and serverless connections; it also caps concurrent connections and helps you avoid too many connections.
- SupaMigrate connects through the pooler by default for exactly this reason — the browser and any CI-style runner reach an IPv4-compatible endpoint instead of the IPv6-only direct host. See what a connection pooler is for the underlying mechanism.
Frequently asked questions
- Why does it work on my laptop but fail in CI or a serverless function?
- Your laptop usually has a working IPv6 route, so it can reach the direct db.<ref>.supabase.co host. Most CI runners, serverless platforms, and Edge runtimes are IPv4-only, so the same IPv6 address is unroutable and the socket fails with ENETUNREACH.
- Is the direct host down or is my project broken?
- Neither. db.<ref>.supabase.co resolves to an IPv6 address by design and is reachable from IPv6-capable networks. The failure is purely a routing problem on the client side. Switch to the pooler host to get an IPv4-compatible endpoint.
- Which pooler port should I use — 6543 or 5432?
- Use 6543 for transaction mode (short-lived connections, serverless, migrations) and 5432 for session mode (long-lived connections, or when you need session-level features like prepared statements and LISTEN/NOTIFY).
Related errors