tailscale/tailscale · critical

starting tailscaled failed: %w

Error message

starting tailscaled failed: %w

What it means

tailscaled.go:41 wraps a failure of exec.Command("tailscaled", ...).Start(): the process could not even be launched. In Go this happens when the binary is not found in PATH, is not executable, or has an exec format error (wrong architecture) — distinct from tailscaled exiting later, which surfaces elsewhere.

Source

Thrown at cmd/containerboot/tailscaled.go:41

	"tailscale.com/client/local"
)

func startTailscaled(ctx context.Context, cfg *settings) (*local.Client, *os.Process, error) {
	args := tailscaledArgs(cfg)
	// tailscaled runs without context, since it needs to persist
	// beyond the startup timeout in ctx.
	cmd := exec.Command("tailscaled", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true,
	}
	if cfg.CertShareMode != "" {
		cmd.Env = append(os.Environ(), "TS_CERT_SHARE_MODE="+cfg.CertShareMode)
	}
	log.Printf("Starting tailscaled")
	if err := cmd.Start(); err != nil {
		return nil, nil, fmt.Errorf("starting tailscaled failed: %w", err)
	}

	// Wait for the socket file to appear, otherwise API ops will racily fail.
	log.Printf("Waiting for tailscaled socket at %s", cfg.Socket)
	for {
		if ctx.Err() != nil {
			return nil, nil, errors.New("timed out waiting for tailscaled socket")
		}
		_, err := os.Stat(cfg.Socket)
		if errors.Is(err, fs.ErrNotExist) {
			time.Sleep(100 * time.Millisecond)
			continue
		} else if err != nil {
			return nil, nil, fmt.Errorf("error waiting for tailscaled socket: %w", err)
		}
		break
	}

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Verify the binary exists and runs: docker run --rm <image> tailscaled --version
  2. Use the official tailscale image (or derive from it) so containerboot and tailscaled ship together
  3. Confirm the image architecture matches the node (kubectl get node -o jsonpath='{.status.nodeInfo.architecture}')
  4. Check the pod does not override PATH or mask the binary directory with mounts

Example fix

# before
FROM debian:bookworm-slim
COPY containerboot /containerboot
# tailscaled never installed
# after
FROM tailscale/tailscale:latest
COPY containerboot /containerboot
Defensive patterns

Strategy: validation

Validate before calling

// Image build/preflight: containerboot execs 'tailscaled' by name; assert it resolves.
if _, err := exec.LookPath("tailscaled"); err != nil {
    log.Fatal("tailscaled binary missing from PATH: use the official tailscale image as base")
}

Prevention

When it happens

Trigger: Container image lacks the tailscaled binary (overwritten entrypoint, distroless mismatch, broken build); PATH env in the pod excludes the binary directory; running an arm64 image on amd64 nodes or vice versa.

Common situations: Custom Dockerfiles that copy containerboot but not tailscaled; image tags pulled for the wrong platform; securityContext or volume mounts shadowing /usr/sbin where tailscaled lives.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/5c46a865e975e1bc. Report an issue: GitHub.