netbirdio/netbird · error
startup: %w
Error message
startup: %w
What it means
Returned by Client.Start when the ConnectClient run loop exits with an error before the engine finishes starting (the 'startup' channel path). This is the engine's permanent/startup backoff error: interface creation failure, management stream failure, or any engine subsystem that aborts during initial bring-up. It is distinct from the context-deadline path: here the run loop itself failed.
Source
Thrown at client/embed/embed.go:293
if err := client.Run(run, ""); err != nil {
clientErr <- err
}
}()
select {
case <-startCtx.Done():
// ConnectClient.Stop now cancels its own run context and waits for the
// run loop to tear the engine down, so this cancel() is no longer
// required to break the deadlock and could be removed. It is kept as a
// defensive belt-and-suspenders: cancelling the parent context first
// guarantees the run loop is unblocked even if Stop's contract regresses.
cancel()
if stopErr := client.Stop(); stopErr != nil {
return fmt.Errorf("stop error after context done. Stop error: %w. Context done: %w", stopErr, startCtx.Err())
}
return startCtx.Err()
case err := <-clientErr:
return fmt.Errorf("startup: %w", err)
case <-run:
}
c.connect = client
c.cancel = cancel
return nil
}
// Stop gracefully stops the client.
// Pass a context with a deadline to limit the time spent waiting for the engine to stop.
func (c *Client) Stop(ctx context.Context) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.connect == nil {
return ErrClientNotStarted
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Unwrap the error to find which subsystem failed: 'new wg interface' points at TUN/netstack/privileges, stream errors at management.
- If NoUserspace=true, ensure the process has the required privileges (root/CAP_NET_ADMIN) and kernel WireGuard support; otherwise keep userspace mode.
- Check management connectivity and protocol compatibility, then retry Start with a new client.
- Enable debug logging (Options.LogLevel "debug") to get the engine-side reason, which is often logged rather than returned.
Defensive patterns
Strategy: try-catch
Try / catch
if err := client.Start(ctx); err != nil {
if strings.Contains(err.Error(), "startup:") {
log.Debug-level engine logs carry the real cause; unwrap and classify before retrying
}
} Prevention
- Run with debug logging during integration to capture engine-side startup failures.
- Ensure privileges (root/NET_ADMIN) when using NoUserspace=true.
When it happens
Trigger: Client.Start where newWgIface or engine start fails: no TUN/netstack available in the environment, MTU rejected again at engine level, management connection drops mid-start, or privileged operations fail when NoUserspace=true without root.
Common situations: Running with NoUserspace=true inside a container without NET_ADMIN/root; a host where the netstack/TUN setup fails (seccomp blocking the syscall); management connection reset during initial sync; version skew between embedded client and management protocol.
Related errors
- startup check: management not connected
- startup check: signal not connected
- startup check: no relay servers available (0/%d connected)
- create auth client: %w
- login: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/90f34bd40a1933d7.
Report an issue: GitHub.