netbirdio/netbird · error
jwt token is required
Error message
jwt token is required
What it means
Marshal failure in handleClientSyncResponse (proxy/internal/debug/handler.go:527): protojson's MarshalOptions{EmitUnpopulated, UseProtoNames, Indent, AllowPartial}.Marshal returns an error on the retrieved protobuf sync response. With AllowPartial already set, remaining causes are essentially unsupported/unknown fields or an internally inconsistent message (e.g. a field holding an invalid value such as a bad enum number), and the debug endpoint answers 500 with the marshal error.
Source
Thrown at client/internal/engine_authsession.go:85
// T-WarningLead interactive notification and suppresses the upcoming
// T-FinalWarningLead fallback for the current deadline. No-op when the
// watcher is not running or holds no deadline.
func (e *Engine) DismissSessionWarning() {
if e.sessionWatcher == nil {
return
}
e.sessionWatcher.Dismiss()
}
// ExtendAuthSession asks the management server to refresh the SSO session
// expiry deadline using the supplied JWT, then mirrors the new deadline into
// the daemon's state. The tunnel is untouched; no resync, no reconnect.
//
// Returns the new absolute UTC deadline (or zero time when the server
// reports the peer is not eligible for extension).
func (e *Engine) ExtendAuthSession(ctx context.Context, jwtToken string) (time.Time, error) {
if jwtToken == "" {
return time.Time{}, errors.New("jwt token is required")
}
if e.mgmClient == nil {
return time.Time{}, errors.New("management client is not initialised")
}
info, err := system.GetInfoWithChecks(ctx, e.checks)
if err != nil {
log.Warnf("failed to collect system info for session extend: %v", err)
info = system.GetInfo(ctx)
}
resp, err := e.mgmClient.ExtendAuthSession(info, jwtToken)
if err != nil {
return time.Time{}, fmt.Errorf("extend auth session on management: %w", err)
}
e.ApplySessionDeadline(resp.GetSessionExpiresAt())
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Check version alignment: the proxy's compiled protobuf definitions should match the management version that produced the sync response (redeploy matching versions).
- Read the appended protojson error — it names the offending field.
- Restart the affected account's client to re-fetch a fresh sync response and retry the endpoint.
- If reproducible, capture the raw response and report it — a marshal failure on a server-produced message indicates a proto contract problem.
Defensive patterns
Strategy: fallback
Try / catch
jsonBytes, err := opts.Marshal(syncResp)
if err != nil {
// Fallback: surface the failure explicitly instead of a bare 500 —
// render the error plus proto reflection info so the offending field
// is identifiable, and keep the rest of the debug page usable.
http.Error(w, "Error marshaling sync response: "+err.Error(), http.StatusInternalServerError)
} Prevention
- Deploy proxy and management from matching versions so compiled protos agree with the messages received.
- After version upgrades, hit the syncresponse endpoint for each live account as a smoke test.
- A persistent marshal failure on a freshly synced response is a proto contract bug — capture and report it with version numbers.
When it happens
Trigger: The stored *proto sync response contains data protojson refuses to serialize: an unknown field with unserializable content injected by a version skew between the proxy's compiled proto and what management sent, or an invalid enum/value that fails protojson's internal validation.
Common situations: Management newer/older than the proxy so the sync message contains unexpected field values; a partially populated message that even AllowPartial cannot render; corrupted in-memory state after deserialization issues.
Related errors
- read of the policy table timed out
- sync response persistence is disabled
- wireguard interface not initialized
- host argument required
- invalid user@host format
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/fe3fead0a03ec42c.
Report an issue: GitHub.