Skip to content
Latchkey

dbmate "could not connect" / DATABASE_URL Errors in CI

dbmate connects using DATABASE_URL. It failed either because that variable is missing/malformed, or because the database was not ready. A not-ready database is transient; a missing/bad URL fails identically every run.

What this error means

dbmate up/migrate fails with a connection error or a complaint that DATABASE_URL is not set. The readiness variant clears on retry; the URL variant does not.

dbmate output
Error: unable to open database connection:
dial tcp 127.0.0.1:5432: connect: connection refused
# or
Error: DATABASE_URL environment variable not set

Common causes

Database not ready yet

A service-container database still starting refuses the connection. This is transient and clears once it accepts connections.

DATABASE_URL unset or malformed

dbmate requires a valid DATABASE_URL (with the right scheme, e.g. postgres://...?sslmode=disable). An absent or malformed URL fails before connecting.

Transient network blip

A brief connectivity drop to a remote database causes an intermittent failure that succeeds on retry.

How to fix it

Wait for readiness, then migrate

Block on the database accepting connections before running dbmate.

Terminal
export DATABASE_URL="postgres://app:pass@db:5432/app?sslmode=disable"
until pg_isready -h db -p 5432; do sleep 1; done
dbmate up

Set and validate DATABASE_URL

  1. Provide DATABASE_URL from a secret at the job level.
  2. Confirm the scheme and parameters match the driver (e.g. sslmode for Postgres).
  3. Assert it is set early: test -n "$DATABASE_URL".

How to prevent it

  • Set DATABASE_URL at the job level from a secret.
  • Gate dbmate on a readiness check.
  • Validate the URL scheme/params for the target driver.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →