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
- Check the wrapped text: 'No such container' means it was already removed — the test result itself is unaffected
- Avoid running concurrent cleanup jobs (cron'd docker system prune) while integration tests run
- Retry the hi command if the daemon was transiently unavailable
- 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
- Do not run concurrent external cleanup (docker system prune cron) during test runs
- Use `hi kill`/`hi cleanup` instead of ad-hoc docker commands
- Expect teardown errors to chain after the test result — always check the first error in the chain
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
- cleaning up containers for run %s: %w
- cleaning stale test containers: %w
- pruning networks: %w
- listing containers for run %s: %w
- creating Docker client: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/8ee2ca27cbca550e.
Report an issue: GitHub.