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 need

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Update the account's JWT claims (service import sharing settings) and push the updated claim via the resolver/account update API.
  2. Re-issue the account JWT with the desired exports/imports sharing settings and call UpdateAccountClaims.
  3. 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

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.