Skip to content

fix(cli): fail check on database login errors and read ~/.pgpass - #839

Merged
psteinroe merged 2 commits into
mainfrom
fix/check-db-login-failure
Oct 6, 2026
Merged

psteinroe merged 2 commits into
mainfrom
fix/check-db-login-failure

Conversation

@psteinroe

Copy link
Copy Markdown
Collaborator

check no longer passes silently when the configured database can't be used, and it reads the password from ~/.pgpass / PGPASSFILE the way libpq clients do.

Connection failures fail check

When a database is configured (not disabled), check connects and loads the schema before checking the files. If that fails, it reports a database/connection error, still runs the checks that don't need the database, and exits non-zero. This includes a connection that is still in backoff from an earlier failure in the daemon. The error is visible without a log level:

database/connection ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  × Database error: password authentication failed for user "postgres"

  i The checks that need the database were skipped. Fix the connection settings, or pass --disable-db or set db.disableConnection to check without a database.

This adds a check_database_connection workspace method, which the daemon also serves. The connection outcome is returned as a result value, not an error, because workspace errors lose their type over JSON-RPC. The LSP doesn't call the new method, so its behaviour is unchanged: it backs off and keeps working without the database.

The DatabaseConnectionError diagnostic template didn't interpolate, so dblint printed the literal Database error: {message}. That's fixed too.

disableConnection in the config file is honoured by the CLI

--disable-db was declared as switch with fallback(Some(false)), so the CLI's partial configuration always carried disableConnection: false and overrode true from the config file. That was invisible while failures were silent; it would now fail check. The flag now only sets the value when passed.

Password file

With no password from the config, --password, or PGPASSWORD, the password is looked up in PGPASSFILE, else ~/.pgpass (%APPDATA%\postgresql\pgpass.conf on Windows). If nothing matches, it falls back to the documented default postgres. That fallback is the conservative choice: setups that rely on it keep working.

sqlx 0.8 has pgpass support, but it isn't usable here:

  • It runs only inside PgConnectOptions::new() / URL parsing. We called .host().port().username() after that, so it matched against the environment's defaults, and then we always overwrote the password.
  • It's crate-private and doesn't expose whether it found a password, which we need for the fallback.
  • It deviates from libpq: it doesn't unescape \: / \\ in the password, it falls back to ~/.pgpass when PGPASSFILE has no match, and it checks permissions only on Linux.

So pgpass.rs ports libpq's passwordFromFile/pwdfMatchesString (REL_18_6). Like libpq, it ignores the file on Unix if group or others can access it, or if it isn't a regular file. Connection strings without a password use the same lookup, and keep sqlx's result when it finds nothing.

Follow-ups, not changed here

  • --conn_timeout_secs has the same fallback(Some(10)) pattern, so the CLI overrides connTimeoutSecs from the config file.
  • In daemon mode (--use-server), file diagnostics fail with "Method not found". The client requests pgls/pull_diagnostics, but the server registers pgls/pull_file_diagnostics. This is already the case on main.
  • For an unreachable server, sqlx reports pool timed out while waiting for an open connection rather than the underlying error.

Fixes #834

…ord file

When a database is configured, `check` now connects up front and reports a
failed connection or login as a `database/connection` error with a non-zero
exit, instead of skipping the database-backed checks silently. `--disable-db`
and `db.disableConnection` still check without a database; the config option
was overridden by the CLI default before.

Without a password from the configuration, the connection string, or
PGPASSWORD, the password is looked up in PGPASSFILE or ~/.pgpass as libpq
does, before falling back to the default `postgres`.

Fixes #834
@psteinroe
psteinroe merged commit 2610510 into main Oct 6, 2026
17 of 18 checks passed
@psteinroe
psteinroe deleted the fix/check-db-login-failure branch October 6, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check: a failed database login skips the type check, prints "Checked", and exits 0; ~/.pgpass is not read

1 participant