nats-io/nats-server · error
default sentinel must be a bearer token
Error message
default sentinel must be a bearer token
What it means
After successfully decoding DefaultSentinel, validateTrustedOperators requires it to be a bearer token: a JWT whose UserClaims have BearerToken set (no signature requirement / auth bypass semantics). If the claims are not a bearer token (juc.BearerToken is false and it does not qualify as an exempt scoped user), the server refuses to start with 'default sentinel must be a bearer token'.
Source
Thrown at server/jwt.go:88
func validateTrustedOperators(o *Options) error {
if len(o.TrustedOperators) == 0 {
// if we have no operator, default sentinel shouldn't be set
if o.DefaultSentinel != _EMPTY_ {
return fmt.Errorf("default sentinel requires operators and accounts")
}
return nil
}
if o.DefaultSentinel != _EMPTY_ {
juc, err := jwt.DecodeUserClaims(o.DefaultSentinel)
if err != nil {
return fmt.Errorf("default sentinel JWT not valid")
}
if !juc.BearerToken && juc.IssuerAccount != "" && juc.HasEmptyPermissions() {
// we cannot resolve the account yet - but this looks like a scoped user
// it will be rejected at runtime if not valid
} else if !juc.BearerToken {
return fmt.Errorf("default sentinel must be a bearer token")
}
}
if o.AccountResolver == nil {
return fmt.Errorf("operators require an account resolver to be configured")
}
if len(o.Accounts) > 0 {
return fmt.Errorf("operators do not allow Accounts to be configured directly")
}
if len(o.Users) > 0 || len(o.Nkeys) > 0 {
return fmt.Errorf("operators do not allow users to be configured directly")
}
if len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 {
return fmt.Errorf("conflicting options for 'TrustedKeys' and 'TrustedOperators'")
}
if o.SystemAccount != _EMPTY_ {
foundSys := false
foundNonEmpty := false
for _, op := range o.TrustedOperators {View on GitHub (pinned to 3a66a489d2)
Solutions
- Create the sentinel as a bearer token user: with nsc add the user with bearer token enabled (bearer_token: true in the claims) and re-export the JWT.
- Edit the user in nsc to set BearerToken, then regenerate/update default_sentinel in the config.
- Alternatively, if a scoped user is intended, ensure it has an IssuerAccount and empty permissions so it is accepted as a scoped default user.
- Restart the server and confirm startup passes validation.
Example fix
// before: non-bearer user JWT in config default_sentinel: "eyJ..." // bearer_token missing // after (nsc) $ nsc edit user sentinel --bearer $ nsc describe user sentinel --raw > sentinel.jwt // nats.conf default_sentinel: "<contents of sentinel.jwt>"
Defensive patterns
Strategy: validation
Validate before calling
// Go: ensure the sentinel is a bearer token before configuring
uc, err := jwt.DecodeUserClaims(sentinelJWT)
if err != nil || !uc.BearerToken {
return errors.New("default_sentinel must be a bearer token user JWT")
} Type guard
func isBearerSentinel(tok string) bool {
uc, err := jwt.DecodeUserClaims(tok)
return err == nil && uc.BearerToken
} Prevention
- Create the sentinel user with bearer token enabled in nsc (`bearer_token: true`).
- Check the decoded claims' BearerToken field before deploying.
- Reuse a dedicated sentinel user, not a general scoped user JWT.
- Run config validation as a pre-start gate in automation.
When it happens
Trigger: Configuring default_sentinel with a normal (non-bearer) user JWT — one carrying permissions requiring full claim verification — instead of a bearer-token user created for sentinel purposes.
Common situations: Generating the sentinel user with `nsc` without enabling bearer token (e.g. missing the bearer_token claim or not using `--bearer`); reusing an existing scoped user JWT as the sentinel.
Related errors
- default sentinel requires operators and accounts
- default sentinel JWT not valid
- mqtt authentication token not compatible with presence of us
- no operator key found
- no_auth_user not compatible with Trusted Operator
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1038288bf567c4fd.
Report an issue: GitHub.