nektos/act · error

--health-timeout cannot be negative

Error message

--health-timeout cannot be negative

What it means

Error [87]: After running a command in the container, act calls ExecInspect to fetch the exit code; that API call failed. Act cannot determine success/failure of the step command because the daemon did not answer the inspect request for the finished exec instance.

Source

Thrown at pkg/container/docker_cli.go:589

		copts.healthTimeout != 0 ||
		copts.healthStartPeriod != 0 ||
		copts.healthRetries != 0 ||
		copts.healthStartInterval != 0
	if copts.noHealthcheck {
		if haveHealthSettings {
			return nil, errors.New("--no-healthcheck conflicts with --health-* options")
		}
		healthConfig = &container.HealthConfig{Test: []string{"NONE"}}
	} else if haveHealthSettings {
		var probe []string
		if copts.healthCmd != "" {
			probe = []string{"CMD-SHELL", copts.healthCmd}
		}
		if copts.healthInterval < 0 {
			return nil, errors.New("--health-interval cannot be negative")
		}
		if copts.healthTimeout < 0 {
			return nil, errors.New("--health-timeout cannot be negative")
		}
		if copts.healthRetries < 0 {
			return nil, errors.New("--health-retries cannot be negative")
		}
		if copts.healthStartPeriod < 0 {
			return nil, errors.New("--health-start-period cannot be negative")
		}
		if copts.healthStartInterval < 0 {
			return nil, errors.New("--health-start-interval cannot be negative")
		}

		healthConfig = &container.HealthConfig{
			Test:          probe,
			Interval:      copts.healthInterval,
			Timeout:       copts.healthTimeout,
			StartPeriod:   copts.healthStartPeriod,
			StartInterval: copts.healthStartInterval,
			Retries:       copts.healthRetries,

View on GitHub (pinned to 4f41128141)

Solutions

  1. Check daemon health right after failure: docker info
  2. If proxying the socket (ssh/VPN), extend keepalive/idle timeouts
  3. Re-run the job; if reproducible only for long steps, shorten or split the step
  4. Update Docker Engine to match the moby API version act uses (or set DOCKER_API_VERSION)

Example fix

# before: idle ssh tunnel drops
ssh -L /tmp/docker.sock:/var/run/docker.sock host &
# after: keepalives on
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=6 -L /tmp/docker.sock:/var/run/docker.sock host &
Defensive patterns

Strategy: try-catch

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to inspect exec") {
	// command output already streamed; treat as inconclusive, re-run the step once
}

Prevention

When it happens

Trigger: cr.cli.ExecInspect erroring after waitForCommand completed: daemon connection lost right after command end, exec record garbage-collected by the daemon before inspection, or API version incompatibility on the exec inspect endpoint.

Common situations: Daemon restart racing the end of a step; remote DOCKER_HOST with connection drops under load; very long-running steps where intermediate proxies (ssh -L, VPN) close idle streams.

Understand the failure class

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/bf5581d2cb5bf23f. Report an issue: GitHub.