juanfont/headscale · error

listing stopped containers: %w

Error message

listing stopped containers: %w

What it means

Returned by cleanupStaleTestContainers when ContainerList with status filters (exited, dead) fails. Beyond connectivity/permission causes, this specific call can fail when the daemon rejects the multi-value status filter — e.g. very old Docker engines or proxies (some docker socket proxies whitelist endpoints and filter arguments).

Source

Thrown at cmd/hi/cleanup.go:145

// This is useful for cleaning up leftover containers from previous crashed or interrupted test runs
// without interfering with currently running concurrent tests.
func cleanupStaleTestContainers(ctx context.Context) error {
	cli, err := createDockerClient(ctx)
	if err != nil {
		return fmt.Errorf("creating Docker client: %w", err)
	}
	defer cli.Close()

	// Only get stopped/exited containers
	containers, err := cli.ContainerList(ctx, container.ListOptions{
		All: true,
		Filters: filters.NewArgs(
			filters.Arg("status", "exited"),
			filters.Arg("status", "dead"),
		),
	})
	if err != nil {
		return fmt.Errorf("listing stopped containers: %w", err)
	}

	removed := 0

	for _, cont := range containers {
		// Only remove containers that look like test containers
		if isTestContainerName(cont.Names) {
			if killAndRemove(ctx, cli, cont) {
				removed++
			}
		}
	}

	if removed > 0 {
		fmt.Printf("Removed %d stale test containers\n", removed)
	}

	return nil

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Test manually: docker ps -a --filter status=exited --filter status=dead
  2. If using a socket proxy, allow the /containers/json endpoint (and container removal) through it
  3. Retry once the daemon is reachable; check `docker version`
  4. Unpin DOCKER_API_VERSION if set to an incompatible value

Example fix

# docker-socket-proxy: permit container listing
-e CONTAINERS=1
Defensive patterns

Strategy: validation

Validate before calling

# Verify the exact filter combination hi uses
docker ps -a --filter status=exited --filter status=dead

Try / catch

Reproduce the filtered listing manually; proxy/whitelist problems show up immediately there and can be fixed before re-running hi.

Prevention

When it happens

Trigger: Running pre-test cleanup behind a restricted docker API proxy that blocks or mangles the /containers/json?filters= call; daemon restarting; API version mismatch; permission denial on the socket.

Common situations: CI images using tecnativa/docker-socket-proxy or similar with a narrow endpoint whitelist; old Docker versions; transient daemon unavailability; shared daemons with ACLs.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/ca2551bc162caa38. Report an issue: GitHub.