docker/compose · error

application not healthy after %s

Error message

application not healthy after %s

What it means

With --wait (options.Wait dependencies), compose waits for dependency health/success conditions under an optional WaitTimeout. When the context deadline expires before waitDependencies finishes, the generic deadline error is translated into this user-facing timeout message including the configured duration.

Source

Thrown at pkg/compose/start.go:90

	if options.Wait {
		depends := types.DependsOnConfig{}
		for _, s := range project.Services {
			depends[s.Name] = types.ServiceDependency{
				Condition: getDependencyCondition(s, project),
				Required:  true,
			}
		}
		if options.WaitTimeout > 0 {
			withTimeout, cancel := context.WithTimeout(ctx, options.WaitTimeout)
			ctx = withTimeout
			defer cancel()
		}

		err = s.waitDependencies(ctx, project, project.Name, depends, containers, 0)
		if err != nil {
			if errors.Is(ctx.Err(), context.DeadlineExceeded) {
				return fmt.Errorf("application not healthy after %s", options.WaitTimeout)
			}
			return err
		}
	}

	return nil
}

// getDependencyCondition checks if service is depended on by other services
// with service_completed_successfully condition, and applies that condition
// instead, or --wait will never finish waiting for one-shot containers
func getDependencyCondition(service types.ServiceConfig, project *types.Project) string {
	for _, services := range project.Services {
		for dependencyService, dependencyConfig := range services.DependsOn {
			if dependencyService == service.Name && dependencyConfig.Condition == types.ServiceConditionCompletedSuccessfully {
				return types.ServiceConditionCompletedSuccessfully
			}
		}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Inspect why the dependency is unhealthy: docker compose ps, docker compose logs <service>, and docker inspect the healthcheck status.
  2. Fix or relax the healthcheck (correct command, larger interval/retries/start_period) so it turns healthy when the service is actually ready.
  3. Increase the wait timeout (--wait-timeout) to exceed realistic startup time.
  4. Fix the dependent service's crash (missing config, bad credentials) that prevents completion.

Example fix

# before
services:
  db:
    image: postgres
    healthcheck:
      test: ["CMD", "pg_isready"]           # flaky/too strict
      interval: 2s
      retries: 1

# after
services:
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
Defensive patterns

Strategy: try-catch

Try / catch

err := composeService.Start(ctx, projectName, api.StartOptions{Wait: true, WaitTimeout: 2 * time.Minute})
if err != nil {
    if strings.Contains(err.Error(), "application not healthy after") {
        // inspect logs/health of dependencies, fix healthcheck, optionally retry with longer timeout
    }
    return err
}

Prevention

When it happens

Trigger: Running up with wait flags and a wait timeout where a depended-on service never reaches healthy (or service_completed_successfully) within options.WaitTimeout — e.g. a database that fails its healthcheck or an app that crashes on boot.

Common situations: Healthcheck intervals too aggressive for slow-starting services; wrong healthcheck command that never succeeds; dependency stuck waiting on another unhealthy dependency; timeout set lower than realistic startup time in CI.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/e092ba83d5a1d9f0. Report an issue: GitHub.