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
- Verify the binary exists and runs: docker run --rm <image> tailscaled --version
- Use the official tailscale image (or derive from it) so containerboot and tailscaled ship together
- Confirm the image architecture matches the node (kubectl get node -o jsonpath='{.status.nodeInfo.architecture}')
- 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
- Base custom images on tailscale/tailscale so containerboot and tailscaled ship together
- Pin image digests per architecture in multi-arch clusters
- CI step: docker run --rm $IMAGE tailscaled --version before promoting the image
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
- error waiting for tailscaled socket: %w
- peer not found
- res.Status
- API response too large
- timed out waiting for tailscaled socket
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/5c46a865e975e1bc.
Report an issue: GitHub.