Skip to content
Latchkey

GitLab CI "services" Health Check Failed - Service Container Not Ready

A services: container (database, cache) must become healthy before your job connects to it. The runner waits for the service’s exposed port; if it never opens, the job fails or your connection is refused.

What this error means

The job log warns the service is not ready, or your script fails with "connection refused" to the service host. The service container started but its port was not accepting connections when the job ran.

Job log
*** WARNING: Service runner-xyz-project-1-concurrent-0-postgres-0 probably didn't start properly.
Health check error:
service "postgres" timeout. The service might not be ready.

Common causes

Service slow to become healthy

The runner polls the service’s exposed port. A heavy service (database initializing) that does not open its port within the health-check window is reported as not ready.

Wrong host alias or port

Services are reachable by their image name or a configured alias. Connecting to localhost instead of the service alias, or the wrong port, fails even when the service is healthy.

Required env not set on the service

Some services need variables to start (e.g. POSTGRES_PASSWORD). Without them the container exits or never becomes ready.

How to fix it

Configure the service and connect by alias

Set required service variables and connect using the service alias/hostname, not localhost.

.gitlab-ci.yml
test:
  image: python:3.12
  services:
    - name: postgres:16
      alias: db
  variables:
    POSTGRES_PASSWORD: secret
    DATABASE_URL: postgres://postgres:secret@db:5432/postgres
  script:
    - python -m pytest

Wait for readiness before using it

  1. Add a short wait/retry loop (e.g. pg_isready) before the first connection.
  2. Confirm you connect to the service alias (db) and correct port.
  3. A momentary slow-start of the service container often passes on a job retry - flaky readiness is transient.

How to prevent it

  • Set all required environment variables for service images.
  • Connect by service alias, not localhost, in shared-network executors.
  • Add an explicit readiness wait before the first service connection.

Frequently asked questions

What causes "services health check"?
The runner polls the service’s exposed port. A heavy service (database initializing) that does not open its port within the health-check window is reported as not ready.
How do I fix services health check?
Set required service variables and connect using the service alias/hostname, not localhost.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card