nats-io/nats-server · error

trusted operators or trusted keys configuration is required

Error message

trusted operators or trusted keys configuration is required for JWT authentication via cookie %q

What it means

JWT-based websocket authentication (websocket.jwt_cookie) requires the server to trust decentralized auth: either trusted operator claims (TrustedOperators) or explicit trusted public NKeys (TrustedKeys). Without one of these, JWTs in the cookie cannot be verified, so the validator refuses to start.

Source

Thrown at server/websocket.go:1171

	// the user to be present.
	if wo.NoAuthUser != _EMPTY_ {
		if err := validateNoAuthUser(o, wo.NoAuthUser); err != nil {
			return err
		}
	}
	// Token/Username not possible if there are users/nkeys
	if len(o.Users) > 0 || len(o.Nkeys) > 0 {
		if wo.Username != _EMPTY_ {
			return fmt.Errorf("websocket authentication username not compatible with presence of users/nkeys")
		}
		if wo.Token != _EMPTY_ {
			return fmt.Errorf("websocket authentication token not compatible with presence of users/nkeys")
		}
	}
	// Using JWT requires Trusted Keys
	if wo.JWTCookie != _EMPTY_ {
		if len(o.TrustedOperators) == 0 && len(o.TrustedKeys) == 0 {
			return fmt.Errorf("trusted operators or trusted keys configuration is required for JWT authentication via cookie %q", wo.JWTCookie)
		}
	}
	if err := validatePinnedCerts(wo.TLSPinnedCerts); err != nil {
		return fmt.Errorf("websocket: %v", err)
	}

	// Check for invalid headers here.
	for key := range wo.Headers {
		k := strings.ToLower(key)
		switch k {
		case "host",
			"content-length",
			"connection",
			"upgrade",
			"nats-no-masking":
			return fmt.Errorf("websocket: invalid header %q not allowed", key)
		}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Add the operator JWT via the operator or resolver config so TrustedOperators is populated
  2. Or add trusted_keys with the operator/signing account public keys to the config
  3. Or remove jwt_cookie if JWT auth is not intended

Example fix

// before
websocket { jwt_cookie: "nats_jwt" }
// after
operator: ./operator.jwt
resolver: MEMORY
websocket { jwt_cookie: "nats_jwt" }
Defensive patterns

Strategy: validation

Validate before calling

if opts.Websocket.JWTCookie != "" && len(opts.TrustedOperators) == 0 && len(opts.TrustedKeys) == 0 {
  return fmt.Errorf("jwt_cookie requires trusted operators or trusted keys")
}

Prevention

When it happens

Trigger: Setting websocket { jwt_cookie: "..." } in a config that has no operator JWT file and no trusted_keys entries.

Common situations: Enabling decentralized JWT auth on a standalone server that was set up without operators; forgetting to sync trusted keys after operator rotation.

Understand the failure class

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/ab22411811fbc05e. Report an issue: GitHub.