netbirdio/netbird · warning

client already started

Error message

client already started

What it means

First branch of forwardWithHeaderAuth's token handling (proxy/internal/auth/middleware.go:472). When a request presents a header scheme token and mw.validateSessionToken returns a non-nil error that is NOT errValidationUnavailable, the token cannot be processed locally (Ed25519 signature verify failure, malformed token) and the client gets 400 'invalid session token'.

Source

Thrown at client/embed/embed.go:32

	"github.com/sirupsen/logrus"
	wgdevice "golang.zx2c4.com/wireguard/device"
	wgnetstack "golang.zx2c4.com/wireguard/tun/netstack"

	"github.com/netbirdio/netbird/client/iface"
	"github.com/netbirdio/netbird/client/iface/netstack"
	"github.com/netbirdio/netbird/client/internal"
	"github.com/netbirdio/netbird/client/internal/auth"
	"github.com/netbirdio/netbird/client/internal/peer"
	"github.com/netbirdio/netbird/client/internal/profilemanager"
	sshcommon "github.com/netbirdio/netbird/client/ssh"
	"github.com/netbirdio/netbird/client/system"
	"github.com/netbirdio/netbird/shared/management/domain"
	mgmProto "github.com/netbirdio/netbird/shared/management/proto"
	"github.com/netbirdio/netbird/util/capture"
)

var (
	ErrClientAlreadyStarted = errors.New("client already started")
	ErrClientNotStarted     = errors.New("client not started")
	ErrEngineNotStarted     = errors.New("engine not started")
	ErrConfigNotInitialized = errors.New("config not initialized")
)

const (
	// PeerStatusConnected indicates the peer is in connected state.
	PeerStatusConnected = peer.StatusConnected
)

// PeerConnStatus is a peer's connection status.
type PeerConnStatus = peer.ConnStatus

// Client manages a netbird embedded client instance.
type Client struct {
	deviceName string
	config     *profilemanager.Config
	mu         sync.Mutex

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Obtain a fresh session token by completing the domain's auth flow again, and send it exactly as issued (no truncation, no extra whitespace).
  2. Confirm the token was issued for this domain: session tokens are validated against the per-domain SessionPublicKey registered via AddDomain.
  3. If the error started after a key change or management/proxy reconfiguration, re-issue tokens and verify the public key configured for the domain matches the management signing key.
  4. Check the proxy log for the underlying validateSessionToken error to distinguish 'malformed' from 'signature verification failed'.

Example fix

# before: stale/mangled token
curl -H 'X-Api-Token: abc123…truncated' https://app.example.com/
# -> 400 invalid session token

# after: freshly issued token, sent verbatim
curl -H "X-Api-Token: $NB_SESSION_TOKEN" https://app.example.com/
Defensive patterns

Strategy: validation

Validate before calling

// Before sending: cheap sanity check that the token is the expected shape
// (opaque session token, no stray whitespace/newlines).
func looksLikeSessionToken(tok string) bool {
    tok = strings.TrimSpace(tok)
    return tok != "" && !strings.ContainsAny(tok, " \t\r\n")
}

Try / catch

resp, err := client.Do(req)
if err == nil && resp.StatusCode == http.StatusBadRequest {
    // 400 'invalid session token': the token failed local verification.
    // Re-run the domain's auth flow and replace the stored token; do not retry unchanged.
}

Prevention

When it happens

Trigger: Calling the domain with the scheme's header (e.g. Authorization or X-Api-Token per the header scheme) carrying a token that is not a valid session token signed by the domain's SessionPublicKey: garbage string, token signed for a different domain/key, truncated or base64-mangled value, or an expired-token parse error from the local validator.

Common situations: Script or API client with a copy-pasted token that picked up whitespace/newlines; tokens issued before a session key rotation (AddDomain re-registered with a new public key); sending an IdP access token where a proxy session token is expected; key mismatch between management and proxy after reconfiguration.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/247a5dbf0cd2f188. Report an issue: GitHub.