nats-io/nats-server · error
system_account in config and operator JWT must be identical
Error message
system_account in config and operator JWT must be identical
What it means
When a system_account is set in the config, at least one operator JWT must declare the same system account. This error is thrown when operators define system accounts but none matches the config value, indicating an inconsistent trust setup.
Source
Thrown at server/jwt.go:116
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 {
if op.SystemAccount != _EMPTY_ {
foundNonEmpty = true
}
if op.SystemAccount == o.SystemAccount {
foundSys = true
break
}
}
if foundNonEmpty && !foundSys {
return fmt.Errorf("system_account in config and operator JWT must be identical")
}
} else if o.TrustedOperators[0].SystemAccount == _EMPTY_ {
// In case the system account is neither defined in config nor in the first operator.
// If it would be needed due to the nats account resolver, raise an error.
switch o.AccountResolver.(type) {
case *DirAccResolver, *CacheDirAccResolver:
return fmt.Errorf("using nats based account resolver - the system account needs to be specified in configuration or the operator jwt")
}
}
srvMajor, srvMinor, srvUpdate, _ := versionComponents(VERSION)
for _, opc := range o.TrustedOperators {
if major, minor, update, err := jwt.ParseServerVersion(opc.AssertServerVersion); err != nil {
return fmt.Errorf("operator %s expects version %s got error instead: %s",
opc.Subject, opc.AssertServerVersion, err)
} else if major > srvMajor {
return fmt.Errorf("operator %s expected major version %d > server major version %d",
opc.Subject, major, srvMajor)View on GitHub (pinned to 3a66a489d2)
Solutions
- Make the config `system_account` identical to the one in the operator JWT(s)
- Regenerate operator JWTs with the correct system account: `nsc edit operator --system-account AD...` then redeploy the updated JWT
Example fix
// before system_account: ADOLD... // after (match the operator JWT's system account) system_account: ADNEW...
Defensive patterns
Strategy: validation
Validate before calling
// Go: ensure operator system accounts match config
for _, op := range o.TrustedOperators {
if op.SystemAccount != "" && o.SystemAccount != "" && op.SystemAccount != o.SystemAccount {
return fmt.Errorf("system account mismatch with operator")
}
} Prevention
- Generate both operator JWT and config system_account from the same nsc operator
- Re-run `nsc describe operator` after any system account change and sync the config
- Diff system_account values between config and JWT in deployment scripts
When it happens
Trigger: Config has `system_account: AD...` and one or more operator JWTs whose SystemAccount is non-empty but different (or none equal to the config value); validateOptions fails.
Common situations: Re-keying or recreating the system account with nsc and forgetting to update either the config or re-issue operator JWTs; copying an operator JWT from another deployment.
Related errors
- operators require an account resolver to be configured
- operators do not allow Accounts to be configured directly
- operators do not allow users to be configured directly
- conflicting options for 'TrustedKeys' and 'TrustedOperators'
- using nats based account resolver - the system account needs
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/b890412cee7fa35c.
Report an issue: GitHub.