juanfont/headscale · warning

removing test container: %w

Error message

removing test container: %w

What it means

Returned by cleanupAfterTest when cli.ContainerRemove with Force:true fails for the main test-suite container (headscale-test-suite-<runID>). Docker returns 404 if the container already vanished, 409 if it cannot be force-removed at this moment, and connection errors if the daemon is gone. Because this runs after a test finishes, it commonly masks (chains after) the test's own result.

Source

Thrown at cmd/hi/cleanup.go:42

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

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

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Check the wrapped text: 'No such container' means it was already removed — the test result itself is unaffected
  2. Avoid running concurrent cleanup jobs (cron'd docker system prune) while integration tests run
  3. Retry the hi command if the daemon was transiently unavailable
  4. Use `hi cleanup` / `hi kill` deliberately instead of ad-hoc docker commands so run-ID labels stay consistent
Defensive patterns

Strategy: try-catch

Validate before calling

// Before manual removal, check existence — mirroring what hi should tolerate.
// (For hi users: prefer `hi kill` over docker rm.)

Try / catch

In Go, treat errdefs.IsNotFound(err) from ContainerRemove as success (already gone); retry once on 409/500; propagate real connectivity errors. hi users: read the wrapped cause — 'No such container' can be ignored.

Prevention

When it happens

Trigger: The test container exited and was garbage-collected by another cleanup process (404 Not Found); concurrent `hi` runs racing to remove the same container; daemon shutdown during teardown; daemon connectivity loss at the end of a long test.

Common situations: Running two `hi` invocations against the same Docker host; aggressive external cleanup scripts (docker system prune -f on a timer) removing stopped containers; Docker Desktop restarting mid-run; CI agents reaping resources.

Related errors


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