netbirdio/netbird · warning

engine not started

Error message

engine not started

What it means

The !result.Valid branch in forwardWithHeaderAuth (middleware.go:478). validateSessionToken completed successfully (no transport error) but the validator judged the session invalid — for OIDC tokens this is management's ValidateSession returning Valid=false (group access revoked, session expired server-side); for local methods the Ed25519 signature/claims check failed. The captured data is seeded with whatever identity info came back, then the client gets 401.

Source

Thrown at client/embed/embed.go:34

	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
	cancel     context.CancelFunc
	setupKey   string

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Re-authenticate to get a new session token; if the denial is group-based, request access to the required group first.
  2. Inspect management's 'Session validation denied' debug log (domain, denied_reason, user_id) to see exactly why Valid was false.
  3. If sessions expire too fast for your workload, raise the domain's session expiration when registering it.
  4. Confirm the token is being sent to the same domain it was issued for.
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: track token issue time and drop it before the domain's
// session expiration so you re-auth proactively.
func tokenFresh(issuedAt time.Time, ttl time.Duration) bool {
    return time.Since(issuedAt) < ttl
}

Try / catch

resp, err := client.Do(req)
if err == nil && resp.StatusCode == http.StatusUnauthorized {
    // Well-formed token but denied (revoked/expired/group loss):
    // re-authenticate through the domain's flow; retrying the same token cannot succeed.
}

Prevention

When it happens

Trigger: Presenting a well-formed header session token whose session is no longer authorized: user removed from the group granting access, session expired per the domain's SessionExpiration, session revoked in management, or a signature that parses but does not verify against the domain key.

Common situations: Access revoked while an automation kept using the old token; token older than the configured session expiration; group/policy changes in management making ValidateSession deny; the operator tightened the service's allowed groups.

Related errors


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