Skip to content
Latchkey

GitHub Actions Service Container Unhealthy - Postgres/Redis Not Ready

A job that uses a service container fails because the database or cache never reports healthy, or steps connect before it is ready - typically a missing health check or a port mismatch.

What this error means

The job fails during "Initialize containers", or a step gets "connection refused" connecting to the service, because the container was not ready when the step ran.

Actions log
Error: Failed to initialize container postgres:16: health check never passed
# or
psql: error: connection to server at "localhost", port 5432 failed: Connection refused

Common causes

No or failing health check

Without a health check, GitHub cannot tell when the service is ready, so steps may run before the database accepts connections.

Port or host mismatch

Steps must connect to the mapped port on localhost (for container-on-host jobs) or the service name (for container jobs). Using the wrong host/port refuses the connection.

How to fix it

Add a health check and map the port

Define a health check so the job waits for readiness, and connect to the mapped port.

.github/workflows/ci.yml
services:
  postgres:
    image: postgres:16
    env: { POSTGRES_PASSWORD: pw }
    ports: ['5432:5432']
    options: >-
      --health-cmd "pg_isready -U postgres"
      --health-interval 10s --health-timeout 5s --health-retries 5

Connect to the right host and wait

  1. From a job running on the host, connect to localhost on the mapped port.
  2. From a container job, connect to the service by its label name (e.g. host postgres).
  3. Add a short wait/retry loop in the step if the client needs the DB fully initialized.

How to prevent it

  • Always define a health check for service containers.
  • Map and connect to the correct port/host for your job type.
  • Retry the first connection so initialization races do not fail the job.

Related guides

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