juanfont/headscale · error
cleaning stale test containers: %w
Error message
cleaning stale test containers: %w
What it means
Returned by cleanupBeforeTest in the hi integration-test runner when cleanupStaleTestContainers fails. That helper creates a Docker client and lists containers filtered to status exited/dead, so failures are almost always Docker daemon connectivity, permissions, or a malformed filter. The error wraps the underlying cause with %w, so the text after the colon identifies the real problem.
Source
Thrown at cmd/hi/cleanup.go:25
"os"
"path/filepath"
"strings"
"time"
"github.com/cenkalti/backoff/v5"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
)
// cleanupBeforeTest performs cleanup operations before running tests.
// Only removes stale (stopped/exited) test containers to avoid interfering with concurrent test runs.
func cleanupBeforeTest(ctx context.Context) error {
err := cleanupStaleTestContainers(ctx)
if err != nil {
return fmt.Errorf("cleaning stale test containers: %w", err)
}
if err := pruneDockerNetworks(ctx); err != nil { //nolint:noinlineerr
return fmt.Errorf("pruning networks: %w", err)
}
return nil
}
// cleanupAfterTest removes the test container and all associated integration test containers for the run.
func cleanupAfterTest(ctx context.Context, cli *client.Client, containerID, runID string) error {
// Remove the main test container
err := cli.ContainerRemove(ctx, containerID, container.RemoveOptions{
Force: true,
})
if err != nil {
return fmt.Errorf("removing test container: %w", err)
}View on GitHub (pinned to 565fd254d0)
Solutions
- Start Docker and verify with `docker ps` — the same permission context is what the test runner uses
- Check DOCKER_HOST and DOCKER_CONTEXT environment variables; unset them or point them at a live daemon
- Add your user to the docker group (sudo usermod -aG docker $USER) and re-login, or run with adequate privileges
- Read the wrapped error text after 'cleaning stale test containers:' — it names the exact Docker API failure
- If the environment has no usable Docker, run `hi doctor` to diagnose the setup
Example fix
# before: daemon not running go run ./cmd/hi run TestACL # error: cleaning stale test containers: ... connect /var/run/docker.sock # after systemctl start docker # or start Docker Desktop go run ./cmd/hi run TestACL
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: confirm a Docker daemon is reachable before running hi.
func dockerReachable() bool {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return false
}
defer cli.Close()
_, err = cli.Info(context.Background())
return err == nil
} Try / catch
Wrap the hi invocation; on failure inspect errors.Unwrap — daemon connectivity errors are retryable after starting Docker, permission errors are not.
Prevention
- Run `go run ./cmd/hi doctor` before test sessions
- Keep DOCKER_HOST/DOCKER_CONTEXT pointed at a live daemon; unset stale values
- Ensure the user is in the docker group before starting work
- Note that pre-test cleanup failure is logged as a warning when CleanBefore is set — check verbose output
When it happens
Trigger: Running `hi run` (or any command that triggers pre-test cleanup) when the Docker daemon is stopped, DOCKER_HOST points to an unreachable socket, the user lacks permission on /var/run/docker.sock, or the Docker API version on the host rejects the status filter combination.
Common situations: Docker Desktop not started; running as a non-root user outside the docker group; DOCKER_HOST/DOCKER_CONTEXT env vars pointing at a stale remote daemon; rootless Docker not running; older Docker engines that do not support the 'dead' status filter.
Related errors
- pruning networks: %w
- creating Docker client: %w
- removing test container: %w
- cleaning up containers for run %s: %w
- creating Docker client: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/7ff3eedbcc3195f7.
Report an issue: GitHub.