juanfont/headscale · error

building headscale: %w

Error message

building headscale: %w

What it means

"building headscale: %w" at cmd/dev/main.go:138 wraps build.Run() of `go build -o <tmpDir>/headscale ./cmd/headscale` executed by cmd/dev. The tool compiles the real server binary into the scratch dir before serving; any compile error, missing toolchain, or write failure surfaces here. Stdout/stderr of the go build are already streamed to the console (build.Stdout/Stderr = os.Stdout/os.Stderr), so the actual compiler diagnostics appear above this error.

Source

Thrown at cmd/dev/main.go:138

	if err != nil {
		return fmt.Errorf("writing config: %w", err)
	}

	// Build headscale.
	fmt.Println("Building headscale...")

	hsBin := filepath.Join(tmpDir, "headscale")

	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	build := exec.CommandContext(ctx, "go", "build", "-o", hsBin, "./cmd/headscale")
	build.Stdout = os.Stdout
	build.Stderr = os.Stderr

	err = build.Run()
	if err != nil {
		return fmt.Errorf("building headscale: %w", err)
	}

	// Start headscale serve.
	fmt.Println("Starting headscale server...")

	serve := exec.CommandContext(ctx, hsBin, "serve", "-c", configPath)
	serve.Stdout = os.Stdout
	serve.Stderr = os.Stderr

	err = serve.Start()
	if err != nil {
		return fmt.Errorf("starting headscale: %w", err)
	}

	// Wait for server to be ready.
	healthURL := fmt.Sprintf("http://127.0.0.1:%d/health", *port)

	err = waitForHealth(ctx, healthURL, 30*time.Second)

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Read the compiler output printed before the error — fix the reported source lines first
  2. Enter the pinned toolchain: `nix develop` then re-run `go run ./cmd/dev`
  3. Verify `go version` >= 1.26.1 and `go build ./cmd/headscale` succeeds standalone

Example fix

# before
system go   # old toolchain, fails at go.mod's 1.26.1 minimum
go run ./cmd/dev

# after
nix develop -c go run ./cmd/dev
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the toolchain compiles before invoking the dev harness
build := exec.Command("go", "build", "./cmd/headscale")
if err := build.Run(); err != nil {
	return fmt.Errorf("tree does not compile, fix first: %w", err)
}

Try / catch

if err := build.Run(); err != nil {
	// compiler diagnostics were already streamed; surface exit cause only
	if ctx.Err() != nil {
		return nil // interrupted build is an expected shutdown
	}
	return fmt.Errorf("building headscale: %w", err)
}

Prevention

When it happens

Trigger: Running `go run ./cmd/dev` on a tree with compile errors; Go toolchain not installed or older than go.mod's 1.26.1 minimum; GOFLAGS/GOOS misconfigured so the binary is written for the wrong platform; read-only GOCACHE; no write access to the tmpDir.

Common situations: Pulling a branch mid-refactor; CI image with an older Go; a stale nix shell (AGENTS.md pins Go 1.26.1 via `nix develop`); GOFLAGS=-mod=vendor without a vendor dir.

Related errors


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