juanfont/headscale · error
starting container: %w
Error message
starting container: %w
What it means
Returned when `cli.ContainerStart` fails for the freshly created test container. Creation succeeded but the daemon refused to start — most often due to port conflicts on published ports, invalid bind mounts, or runtime constraints. The container remains created (not running), so cleanup is still needed.
Source
Thrown at cmd/hi/docker.go:96
log.Printf("Command: %s", strings.Join(goTestCmd, " "))
}
imageName := "golang:" + config.GoVersion
if err := ensureImageAvailable(ctx, cli, imageName, config.Verbose); err != nil { //nolint:noinlineerr
return fmt.Errorf("ensuring image availability: %w", err)
}
resp, err := createGoTestContainer(ctx, cli, config, containerName, absLogsDir, goTestCmd)
if err != nil {
return fmt.Errorf("creating container: %w", err)
}
if config.Verbose {
log.Printf("Created container: %s", resp.ID)
}
if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { //nolint:noinlineerr
return fmt.Errorf("starting container: %w", err)
}
log.Printf("Starting test: %s", config.TestPattern)
log.Printf("Run ID: %s", runID)
log.Printf("Monitor with: docker logs -f %s", containerName)
log.Printf("Logs directory: %s", logsDir)
// Start stats collection for container resource monitoring (if enabled)
var statsCollector *StatsCollector
if config.Stats {
var err error
statsCollector, err = NewStatsCollector(ctx)
if err != nil {
if config.Verbose {
log.Printf("Warning: failed to create stats collector: %v", err)
}View on GitHub (pinned to 565fd254d0)
Solutions
- Find and stop the port/container conflict: `docker ps` then `docker rm -f` the stale containers, or `go run ./cmd/hi clean`.
- Avoid running two `hi run` commands concurrently against the same Docker daemon.
- Read the wrapped daemon message — it names the conflicting port or mount.
- Enable swap-accounting cgroup flags if memory limits are set (kernel cmdline `swapaccount=1`).
Defensive patterns
Strategy: validation
Validate before calling
// free the ports the test will publish before starting
for _, port := range []string{"8080/tcp", "3478/udp"} { // adjust to actual published set
out, _ := exec.Command("sh", "-c", fmt.Sprintf(
"docker ps -q --filter publish=%s", port)).Output()
if len(strings.TrimSpace(string(out))) > 0 {
return fmt.Errorf("port %s already bound by another container", port)
}
} Try / catch
if err := runDockerTest(ctx, config); err != nil {
if strings.Contains(err.Error(), "starting container") {
// inspect `docker ps -a` for the created-but-not-started container,
// resolve the port/mount conflict named in the wrapped daemon error, then retry
}
} Prevention
- Stop or remove containers bound to the test's ports before each run.
- Serialize hi runs against a single daemon.
- Read the daemon's own message inside the wrapped error — it names the conflicting resource.
When it happens
Trigger: Another `hi` run (or any process) already binds the headscale/Tailscale ports this container publishes; the bind-mounted logs dir disappeared between create and start; the daemon cannot apply the host config (memory limits without swap accounting: 'WARNING: Your kernel does not support swap limit capabilities').
Common situations: Two concurrent `hi run` invocations racing for the same ports; leftover tailscale/headscale containers from a previous run; Linux hosts missing cgroup swap accounting when memory limits are configured.
Related errors
- ensuring image availability: %w
- creating container: %w
- executing test: %w
- getting container logs: %w
- waiting for container: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/f4ef450ff12bbed4.
Report an issue: GitHub.