Replies: 4 comments
1. The Immediate Diagnostic: Test Password Authentication Without IPv6Since your local network lacks IPv6 and you cannot connect to the Direct endpoint, you can test whether PostgreSQL's local Run this in the SQL Editor: -- Enable dblink extension if not already present
CREATE EXTENSION IF NOT EXISTS dblink;
-- Test direct local loopback authentication
SELECT * FROM dblink(
'host=127.0.0.1 port=5432 dbname=postgres user=otd_integration_login_v2 password=YOUR_EXACT_PASSWORD',
'SELECT 1'
) AS t(val int);
2. Why Supavisor Rejects Custom LOGIN Roles with
|
|
The Your test results actually strengthen that reading:
Three quick isolations worth attaching to SU-509174:
When you reply to the ticket, the most useful framing for support is: "custom LOGIN role authenticates fine server-side (dblink loopback) but fails 28P01 through the shared pooler for two different roles, with One aggravating factor worth noting for anyone on Free: the direct host is AAAA-only (IPv6), so without the IPv4 add-on there is no v4 fallback path — the pooler is the only route, which makes a registry sync gap a hard blocker rather than an inconvenience. I write about RLS/pooler gotchas at rls.cenkkurtoglu.com — this exact pooler/custom-role class is on the shortlist there. |
|
One thing worth checking before changing role grants: Supabase's current docs explicitly say custom PostgreSQL For shared pooler connections, the username should be Was the project ref omitted from your example for privacy, or is the client actually sending just I also wouldn't grant The docs mention temporary credential caching after password rotation, but since you've reproduced this with a newly created role, your support ticket seems worth pursuing if the connection string is correct. Docs: https://supabase.com/docs/guides/troubleshooting/fatal-password-authentication-failed |
|
Your verification list rules out the usual suspects, and the one that remains is about which pooler you are on rather than the role itself. The Shared Supavisor pooler runs in tenant mode, and a tenant carries a fixed allowlist of users — the roles created through the platform's managed flow ( The decisive test, and the one that also tells you what to do next: 1. Try the direct connection with the same role. The direct connection string bypasses Supavisor's auth entirely — it speaks Postgres's own protocol to your database host. If the custom role authenticates there and fails on the shared pooler, the diagnosis is confirmed in two commands: # direct (no pooler) - use the IPv4 direct host if your network is IPv6-first
psql "postgresql://otd_integration_login_v2.<PASSWORD>@db.<PROJECT_REF>.supabase.co:5432/postgres"
# pooler, for the contrast
psql "postgresql://otd_integration_login_v2.<PASSWORD>@aws-0-eu-west-1.pooler.supabase.com:5432/postgres"If direct works and pooler fails, nothing is wrong with the role; the shared pooler simply is not carrying it yet. 2. The workaround that works today, if you need the pooler: connect as a managed role that is in the tenant set and grant otd_integration_login_v2 to postgres;
-- verify before relying on it:
select pg_has_role(current_user, 'otd_integration_login_v2', 'USAGE') as can_set_role;Then 3. Ask the platform to register the role in the tenant. The request is a one-liner for support: "please add role Two smaller things while you are in there, because they produce the same SQLSTATE and are cheap to exclude:
What is not the cause: SCRAM format (you verified SCRAM-SHA-256, which is what both endpoints want), TLS (your full verification passed), and role attributes ( One note on the dedicated/project pooler, for completeness: on projects that have it, the tenant is yours and the reload story is the same — platform-side. The direct connection remains the only path that needs no allowlist, which is why the RLS-adjacent guidance for restricted roles has always been "direct for migrations and role work, pooler for request traffic as the managed roles." |
Uh oh!
There was an error while loading. Please reload this page.
I have a Supabase Free project in West EU (Ireland) and I am trying to connect a server-side application using a restricted custom PostgreSQL LOGIN role.
The custom role otd_integration_login_v2 has been verified in PostgreSQL:
rolcanlogin = true
password format is SCRAM-SHA-256
rolvaliduntil is null
role is a member of a restricted backend role
it is not superuser and does not have BYPASSRLS
I am using the Shared Supavisor pooler with the documented username format:
otd_integration_login_v2.
I tested both:
Session mode, port 5432
Transaction mode, port 6543
In both cases:
TCP connection succeeds
full TLS verification with the Supabase CA succeeds
PostgreSQL authentication fails with SQLSTATE 28P01
Supavisor logs show:
ClientHandler: Exchange error: password authentication failed for user "otd_integration_login_v2"
and:
SecretChecker not started, using a one-off auth_query connection
To rule out stale password caching, I created a completely new custom LOGIN role with a new password, but it produces the same result.
The Direct Connection host resolves correctly to an IPv6 address on my Windows machine, but my current network cannot route IPv6, so I cannot independently verify the password through the Direct endpoint.
The Shared Pooler is fully reachable over IPv4 and completes TCP/TLS successfully; the failure occurs only during PostgreSQL authentication.
I have also opened Supabase support ticket SU-509174.
Is there any additional configuration required for custom LOGIN roles to authenticate through Shared Supavisor, or could this indicate an issue with Supavisor's auth query/password exchange?
I can provide additional sanitized logs if needed. No credentials or connection strings with passwords will be shared.
All reactions