nats-io/nats-server · error
claim based accounts can not be updated directly
Error message
claim based accounts can not be updated directly
What it means
setServiceImportSharing refuses to modify service imports on claim-based accounts (server/accounts.go:1806). Accounts whose state is derived from an operator-managed claims JWT must be updated through claim updates, not direct in-memory mutation APIs.
Source
Thrown at server/accounts.go:1806
a.mu.RLock()
}
}
a.mu.RUnlock()
return nil
}
// SetServiceImportSharing will allow sharing of information about requests with the export account.
// Used for service latency tracking at the moment.
func (a *Account) SetServiceImportSharing(destination *Account, to string, allow bool) error {
return a.setServiceImportSharing(destination, to, true, allow)
}
// setServiceImportSharing will allow sharing of information about requests with the export account.
func (a *Account) setServiceImportSharing(destination *Account, to string, check, allow bool) error {
a.mu.Lock()
defer a.mu.Unlock()
if check && a.isClaimAccount() {
return fmt.Errorf("claim based accounts can not be updated directly")
}
// We can't use getServiceImportForAccountLocked() here since we are looking
// for the service import with the si.to == to, which may not be the key
// for the service import in the map.
for _, sis := range a.imports.services {
for _, si := range sis {
if si.acc.Name == destination.Name && si.to == to {
si.share = allow
return nil
}
}
}
return fmt.Errorf("service import not found")
}
// AddServiceImport will add a route to an account to send published messages / requests
// to the destination account. From is the local subject to map, To is the
// subject that will appear on the destination account. Destination will needView on GitHub (pinned to 3a66a489d2)
Solutions
- Update the account's JWT claims (service import sharing settings) and push the updated claim via the resolver/account update API.
- Re-issue the account JWT with the desired exports/imports sharing settings and call UpdateAccountClaims.
- If the account is not meant to be claim-based, provision it without JWT backing.
Example fix
// before acc.setServiceImportSharing(dest, "req", true, true) // after claims := jwt.NewAccountClaims(acc.Name) claims.Exports.Add(...) srv.UpdateAccountClaims(oldClaims, claims)
Defensive patterns
Strategy: validation
Validate before calling
if acc.isClaimAccountLike() {
// route through JWT claim update instead
} Try / catch
if err := acc.setServiceImportSharing(dest, to, true, true); err != nil {
if strings.Contains(err.Error(), "claim based accounts") {
// update via UpdateAccountClaims instead
}
} Prevention
- Check whether the account is claim-backed before direct mutation
- Prefer JWT claim updates in operator mode
- Keep account state changes in the claim source of truth
When it happens
Trigger: Calling setServiceImportSharing (directly or via AddServiceImport sharing options) on an Account backed by claims, with check=true.
Common situations: Using embedded server APIs to mutate an account that was created from a JWT in an operator-mode deployment; scripts that mutate accounts in memory and expect them to persist.
Related errors
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/df113abff3237e76.
Report an issue: GitHub.