juanfont/headscale · warning

cleaning up containers for run %s: %w

Error message

cleaning up containers for run %s: %w

What it means

Returned by cleanupAfterTest when killTestContainersByRunID fails. That function lists containers carrying the label hi.run-id=<runID> and force-kills/removes them. The wrapped error is either a Docker client/list failure or, less often, a removal failure, and it names the run ID so you can identify which test run's teardown failed.

Source

Thrown at cmd/hi/cleanup.go:49

	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)
	}

	// Clean up integration test containers for this run only
	if runID != "" {
		err := killTestContainersByRunID(ctx, runID)
		if err != nil {
			return fmt.Errorf("cleaning up containers for run %s: %w", runID, err)
		}
	}

	return nil
}

// killTestContainers terminates and removes all test containers.
func killTestContainers(ctx context.Context) error {
	cli, err := createDockerClient(ctx)
	if err != nil {
		return fmt.Errorf("creating Docker client: %w", err)
	}
	defer cli.Close()

	containers, err := cli.ContainerList(ctx, container.ListOptions{
		All: true,
	})
	if err != nil {

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Read the wrapped cause after 'cleaning up containers for run <id>:' — it distinguishes list vs remove failures
  2. Manually verify with: docker ps -a --filter label=hi.run-id=<runID>
  3. Run `go run ./cmd/hi kill` to sweep leftovers, then retry
  4. Restart/reconnect Docker if the daemon was down

Example fix

# inspect leftovers for the failing run
docker ps -a --filter "label=hi.run-id=<runID>"
# remove them explicitly
docker rm -f $(docker ps -aq --filter "label=hi.run-id=<runID>")
Defensive patterns

Strategy: retry

Validate before calling

# Verify a run's containers before/after teardown
docker ps -a --filter "label=hi.run-id=<runID>"

Try / catch

Log the run ID from the message, inspect leftovers via the label filter, remove them explicitly, then retry the hi command if needed.

Prevention

When it happens

Trigger: Daemon unreachable or user unauthorized at teardown time; containers with the run's label in a state Docker refuses to remove; label-filtered ContainerList failing on very old Docker engines.

Common situations: Docker daemon restarted while tests were running; permissions changed mid-session; leftover labeled containers from a crashed run that are half-removed; remote daemon disconnects.

Related errors


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