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 stringView on GitHub (pinned to 93e97f4bf1)
Solutions
- Re-authenticate to get a new session token; if the denial is group-based, request access to the required group first.
- Inspect management's 'Session validation denied' debug log (domain, denied_reason, user_id) to see exactly why Valid was false.
- If sessions expire too fast for your workload, raise the domain's session expiration when registering it.
- 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
- Treat 401 on a previously working token as 're-auth', never as 'retry'.
- Keep group membership aligned with the service's access policy in management.
- Refresh tokens on a schedule shorter than the domain's SessionExpiration.
- Use management's 'Session validation denied' logs (denied_reason) for root cause.
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
- client already started
- no daemon pipe to connect to
- host argument required
- invalid user@host format
- tun module not available
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/6427731d0d000133.
Report an issue: GitHub.