{"record":{"id":"25b92fe8e8cd52f3","repo":"nats-io/nats-server","slug":"operators-do-not-allow-users-to-be-configured-dire","errorCode":null,"errorMessage":"operators do not allow users to be configured directly","messagePattern":"operators do not allow users to be configured directly","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/jwt.go","lineNumber":98,"sourceCode":"\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"default sentinel JWT not valid\")\n\t\t}\n\n\t\tif !juc.BearerToken && juc.IssuerAccount != \"\" && juc.HasEmptyPermissions() {\n\t\t\t// we cannot resolve the account yet - but this looks like a scoped user\n\t\t\t// it will be rejected at runtime if not valid\n\t\t} else if !juc.BearerToken {\n\t\t\treturn fmt.Errorf(\"default sentinel must be a bearer token\")\n\t\t}\n\t}\n\tif o.AccountResolver == nil {\n\t\treturn fmt.Errorf(\"operators require an account resolver to be configured\")\n\t}\n\tif len(o.Accounts) > 0 {\n\t\treturn fmt.Errorf(\"operators do not allow Accounts to be configured directly\")\n\t}\n\tif len(o.Users) > 0 || len(o.Nkeys) > 0 {\n\t\treturn fmt.Errorf(\"operators do not allow users to be configured directly\")\n\t}\n\tif len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 {\n\t\treturn fmt.Errorf(\"conflicting options for 'TrustedKeys' and 'TrustedOperators'\")\n\t}\n\tif o.SystemAccount != _EMPTY_ {\n\t\tfoundSys := false\n\t\tfoundNonEmpty := false\n\t\tfor _, op := range o.TrustedOperators {\n\t\t\tif op.SystemAccount != _EMPTY_ {\n\t\t\t\tfoundNonEmpty = true\n\t\t\t}\n\t\t\tif op.SystemAccount == o.SystemAccount {\n\t\t\t\tfoundSys = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif foundNonEmpty && !foundSys {\n\t\t\treturn fmt.Errorf(\"system_account in config and operator JWT must be identical\")","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jwt.go#L80-L116","documentation":"Under operator mode, users and nkeys must come from signed account JWTs rather than the server config. This error is thrown when `users` or `nkeys` are listed directly in a config that also declares an operator, because that bypasses operator signing of credentials.","triggerScenarios":"Config has `operator: <jwt>` plus a top-level `users: [...]` or `nkeys: [...]` array; validateOptions aborts startup.","commonSituations":"Keeping old user credentials in the config after adding an operator; testing operator mode by appending it to an existing single-user server config.","solutions":["Remove the `users`/`nkeys` blocks and issue user JWTs signed by the account (nsc add user) served via the resolver","If direct users are needed, remove the `operator` setting and use classic authentication mode"],"exampleFix":"// before\noperator: eyJ...\nusers: [{user: alice, password: pwd}]\n// after\noperator: eyJ...\nresolver: MEMORY\n// create alice's credentials with: nsc add user --name alice","handlingStrategy":"validation","validationCode":"// Go: reject direct users/nkeys in operator mode\nif len(o.TrustedOperators) > 0 && (len(o.Users) > 0 || len(o.Nkeys) > 0) {\n    return fmt.Errorf(\"issue user credentials via nsc instead\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use `nsc add user` to issue credentials instead of config users","Remove legacy users/nkeys blocks during operator migration","Add config linting to catch this combination"],"tags":["nats","jwt","config-validation","operator-mode"],"backgroundTag":"conflicting-config-options","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}