PostgreSQL no pg_hba.conf entry — Fix Host-Based Authentication
Diagnose PostgreSQL FATAL: no pg_hba.conf entry errors by reading pg_hba_file_rules, matching client address and SSL mode, then adding and reloading a host rule.
Symptoms
- FATAL: no pg_hba.conf entry for host "10.20.0.5", user "app", database "app", no encryption
- psql works from localhost but fails from an application pod or CI runner
- The error appears immediately after a database failover or network migration
- Connections using TLS report the same message with SSL encryption instead of no encryption
Possible causes
- The client subnet is missing from pg_hba.conf or is covered by a narrower rule
- A hostssl rule exists but the client connects without TLS, or a hostnossl rule blocks it
- The rule was edited on disk but the server was never reloaded
- The connection lands on a different PostgreSQL instance or a pooler with its own authentication file
Diagnosis steps
Ask the server which file and line it is using
psql -U postgres -c "SHOW hba_file;" -c "SELECT line_number, type, database, user_name, address, auth_method, error FROM pg_hba_file_rules ORDER BY line_number;"Interpretation
The view shows every parsed rule plus a non-null error column for invalid lines. If the client address appears in no address column, the rule simply does not exist.
Reproduce with the exact client address and SSL mode
psql "host=db.internal port=5432 dbname=app user=app sslmode=require" -c 'select inet_client_addr(), ssl from pg_stat_ssl where pid = pg_backend_pid();'Interpretation
A failure before the query runs confirms authentication, not SQL, is the blocker. The message reports whether the client presented TLS.
Compare the client address with the rule coverage
psql -U postgres -c "SELECT name, setting FROM pg_settings WHERE name = 'listen_addresses';" -c "SELECT inet_client_addr();"Interpretation
Verify the client is reaching the intended instance and that its source address falls inside a listed CIDR instead of a single host entry.
Check whether a reload actually happened
psql -U postgres -c "SELECT pg_conf_load_time(), pg_postmaster_start_time();"Interpretation
pg_conf_load_time should be later than your edit. If it matches the startup time, the file was never reloaded.
Root cause
PostgreSQL authorizes each connection against the first matching pg_hba.conf line for its type, database, user, and source address. When no line matches, or a hostssl line requires TLS that the client did not offer, the server rejects the connection before authentication completes. Editing the file alone changes nothing until the postmaster reloads it.
Fix
Add a rule that matches the real client network, user, and database, and choose hostssl when TLS is mandatory. Reload with SELECT pg_reload_conf() rather than restarting. If a pooler such as PgBouncer sits in front, update its auth_file and database list as well. Keep rules ordered from most specific to most general and avoid broad trust entries.
Risk note
A rule such as host all all 0.0.0.0/0 trust exposes the database to every reachable host. Reloading is safe, but a malformed file can make the next connection fail, so validate with pg_hba_file_rules before disconnecting the current session.
Verify the fix
Reconnect from the failing host and confirm the session starts, then run SELECT inet_client_addr(), ssl FROM pg_stat_ssl WHERE pid = pg_backend_pid(); and check the address and TLS state match the intended rule.
The error names the rule that is missing
FATAL: no pg_hba.conf entry for host "10.20.0.5", user "app", database "app", no encryption means the postmaster found no matching line in its host-based authentication file. It is not a wrong password: the server rejected the connection before password verification.
FATAL: no pg_hba.conf entry for host "10.20.0.5", user "app", database "app", no encryption
The trailing no encryption or SSL encryption tells you which transport the client used, which matters when the only matching rule is hostssl.
Inspect the effective rules
Query the parsed file instead of guessing. The error column exposes syntax problems and the line_number matches the file you are editing.
SHOW hba_file;
SELECT line_number, type, database, user_name, address, auth_method, error
FROM pg_hba_file_rules ORDER BY line_number;
Compare the client address reported by inet_client_addr() with the address column. A /32 entry for one pod does not cover a rolling deployment that adds new pod IPs.
Add the narrowest rule that works
# TYPE DATABASE USER ADDRESS METHOD
hostssl app app 10.20.0.0/24 scram-sha-256
Reload and re-check the view. A reload (SELECT pg_reload_conf();) is enough for pg_hba.conf; a restart is not required and would drop every session.
Verify from the failing host
Connect with the original connection string and confirm the negotiated transport:
psql "host=db.internal dbname=app user=app sslmode=require" \
-c "select inet_client_addr(), ssl from pg_stat_ssl where pid = pg_backend_pid();"
If the connection still fails, confirm you edited the file returned by SHOW hba_file on the instance that actually received the connection, and that no pooler terminates authentication first.