You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AUTH_USER sets auth_user in the [pgbouncer] section, which pgbouncer treats as the default for databases that do not name one of their own. But generate_config_db_entry always writes a per-database auth_user:
Connecting as a user absent from userlist.txt, so that the auth_query path runs:
$ psql "postgres://other@pooler:5432/appdb"psql: error: FATAL: password authentication failed for user "ghostuser"
The lookup was attempted as ghostuser, never as the configured AUTH_USER.
The second symptom
The same line explains a confusing error in the default configuration. Started with neither DB_USER nor AUTH_USER, an entry still advertises auth_user=postgres, so an unknown user gets:
C-0x…: appdb/(nouser)@… closing because: password authentication failed for user "postgres"
S-0x…: appdb/postgres@… closing because: password authentication failed for user "postgres"
naming a role the operator never configured. The real situation is that the connecting user is absent from userlist.txt and no usable auth_user exists. Without an auth_user on the entry, pgbouncer would have said so plainly.
How the two came to collide
AUTH_USER arrived in 99b51ec (2019) and is the README's documented route to auth_query. The per-database auth_user arrived much later, in 6591cb9 (2023, #56), as a one-word change:
That fixed a real problem — the forced user= collapsed every client into a single identity on the server — and putting DB_USER into auth_user was the point of it. AUTH_USER is not mentioned anywhere in #56, so the shadowing looks like something nobody had reason to notice: for the four years before, the two variables wrote different settings and could not conflict.
Suggested fix
Reconcile the two rather than undo either:
auth_user = DB_USER when set
AUTH_USER otherwise, when set
omitted otherwise
AUTH_USER becomes usable for the first time since it was added
with neither set, the entry stops advertising a postgres credential nobody configured, and an unknown user gets pgbouncer's own clear message instead of a failure naming postgres
One case to weigh before changing the last line: a mounted AUTH_FILE may hold a postgres credential with no DB_* and no AUTH_USER set, and that setup would lose auth_query if the entry stops defaulting. Keeping the postgres fallback while still honouring AUTH_USER would cover it, at the cost of the confusing error staying.
Related
pooler error: password authentication failed #58 reached the same password authentication failed message from a different cause: their auth_user existed but could not read pg_shadow on RDS. Whatever the reason auth_query cannot run, the error names the auth_user rather than the user who was refused, and the report starts by looking at the wrong credential.
AUTH_USERsetsauth_userin the[pgbouncer]section, which pgbouncer treats as the default for databases that do not name one of their own. Butgenerate_config_db_entryalways writes a per-databaseauth_user:and the per-database value wins. So
AUTH_USERnever applies to a generated entry.Reproducing
Per-entry
auth_userpointing at a role that does not exist, globalAUTH_USERpointing at one that does and whose password is inuserlist.txt:Connecting as a user absent from
userlist.txt, so that theauth_querypath runs:The lookup was attempted as
ghostuser, never as the configuredAUTH_USER.The second symptom
The same line explains a confusing error in the default configuration. Started with neither
DB_USERnorAUTH_USER, an entry still advertisesauth_user=postgres, so an unknown user gets:naming a role the operator never configured. The real situation is that the connecting user is absent from
userlist.txtand no usableauth_userexists. Without anauth_useron the entry, pgbouncer would have said so plainly.How the two came to collide
AUTH_USERarrived in 99b51ec (2019) and is the README's documented route toauth_query. The per-databaseauth_userarrived much later, in 6591cb9 (2023, #56), as a one-word change:That fixed a real problem — the forced
user=collapsed every client into a single identity on the server — and puttingDB_USERintoauth_userwas the point of it.AUTH_USERis not mentioned anywhere in #56, so the shadowing looks like something nobody had reason to notice: for the four years before, the two variables wrote different settings and could not conflict.Suggested fix
Reconcile the two rather than undo either:
DB_USERstill drivesauth_user, and clients still reach the server under their own identityAUTH_USERbecomes usable for the first time since it was addedpostgrescredential nobody configured, and an unknown user gets pgbouncer's own clear message instead of a failure namingpostgresOne case to weigh before changing the last line: a mounted
AUTH_FILEmay hold apostgrescredential with noDB_*and noAUTH_USERset, and that setup would loseauth_queryif the entry stops defaulting. Keeping thepostgresfallback while still honouringAUTH_USERwould cover it, at the cost of the confusing error staying.Related
password authentication failedmessage from a different cause: theirauth_userexisted but could not readpg_shadowon RDS. Whatever the reasonauth_querycannot run, the error names the auth_user rather than the user who was refused, and the report starts by looking at the wrong credential.auth_typecannot check.Reproduced on
edoburu/pgbouncer:latest.Assisted-by: Claude:claude-opus-5[1m]