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

  1. Check version alignment: the proxy's compiled protobuf definitions should match the management version that produced the sync response (redeploy matching versions).
  2. Read the appended protojson error — it names the offending field.
  3. Restart the affected account's client to re-fetch a fresh sync response and retry the endpoint.
  4. 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

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


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