A NATS server cannot resolve one or more accounts required for JetStream operations — the healthz endpoint is reporting an ACCOUNT-type error, indicating that the account’s configuration or JWT could not be loaded, leaving JetStream assets associated with that account in a failed state.
NATS multi-tenancy relies on accounts to isolate users, subjects, and JetStream resources. Each JetStream stream and consumer belongs to an account. When the server starts, it must resolve every account that owns JetStream assets so it can apply the correct limits, permissions, and resource reservations. If an account cannot be resolved, all streams and consumers belonging to that account fail to load.
This is not a partial failure — every JetStream asset in the unresolved account becomes unavailable on this server. If the account owns 50 streams, all 50 are down on this node. For replicated assets, the other replicas on servers that can resolve the account continue operating, but the cluster loses a replica for every affected stream. For R1 assets in the unresolved account, this is a complete outage.
Account resolution failures are particularly dangerous because they often affect many assets simultaneously. A single misconfigured JWT or an unreachable account resolver can take out an entire tenant’s JetStream infrastructure in one failure. Unlike stream-level issues where you troubleshoot one asset at a time, account resolution failures require fixing the account layer before any of its assets can recover.
Account JWT expired or revoked. In deployments using the NATS JWT-based security model, account JWTs have expiration times. An expired JWT cannot be used to resolve the account. Similarly, if the account JWT was explicitly revoked via the operator, resolution fails.
Account resolver unreachable. When using a URL-based account resolver (pointing to an external NATS account server or resolver endpoint), network connectivity issues between the NATS server and the resolver prevent JWT fetching. DNS failures, firewall changes, or resolver downtime all cause this.
Missing or corrupt account JWT in the resolver directory. For file-based or directory-based resolvers, the JWT file for the account may be missing, empty, or contain invalid data. Manual cleanup of the resolver directory or filesystem corruption can cause this.
Operator or account key mismatch. The account JWT was signed by an operator key that the server does not trust. This happens when operator keys are rotated without updating the server’s trusted operator configuration, or when an account JWT from a different operator is accidentally placed in the resolver.
Memory resolver with stale configuration. The server’s accounts block in the configuration file references an account that has been removed or renamed. On restart, the server cannot find a matching account definition.
NATS account server version incompatibility. An upgraded NATS account server may return JWTs in a format that an older NATS server cannot parse, or vice versa.
nats server request healthz --name <server_name>The response will identify the account that failed resolution:
1status: error2error: "account resolution failed: ABCDEF123456..."The identifier is the account’s public key (NKey). Map this to a human-readable account name using your operator configuration.
nats server report accountsThis lists all known accounts on the server. The failed account may be missing from this list entirely or may show zero connections and zero JetStream assets despite expecting them.
If using JWT-based auth, check whether the account JWT is valid:
# Decode and verify the JWTnsc describe account <account_name>
# Check expirationnsc describe account <account_name> | grep -i "expires"If the JWT is expired, it needs to be reissued and pushed to the resolver.
For URL-based resolvers, verify the server can reach the resolver endpoint:
# Check if the resolver URL is accessible from the servercurl -s http://<resolver_host>:<resolver_port>/jwt/v1/accounts/<account_public_key>A 200 response with a valid JWT means the resolver is working. A connection timeout, 404, or 500 indicates the resolver is the problem.
# Server logs will detail the resolution failure# Look for entries like:# [ERR] Unable to resolve account "ABCDEF123456": fetch timeout# [ERR] Account JWT verification failed: expired# [ERR] Account resolution for JetStream assets failedThe log message distinguishes between network errors (timeout, connection refused), authentication errors (bad signature, expired), and missing account errors.
List all JetStream assets in the affected account. Determine how many streams and consumers are impacted:
nats stream list # account is selected via NATS context/credentialsnats consumer list <stream_name> --account <account_name>If these commands fail (because the account is unresolved), check other servers in the cluster where the account may still be resolved.
Reissue an expired JWT. If the account JWT has expired, generate a new one with a longer validity period:
# Reissue the account JWTnsc generate creds --account <account_name>
# Push the updated JWT to the resolvernsc push --account <account_name>Restart the resolver or fix connectivity. If the URL resolver is unreachable, restart the NATS account server or fix the network path. Then trigger a reload on the NATS server:
nats-server --signal reloadA config reload causes the server to re-resolve accounts, picking up the now-available resolver.
Restore a missing JWT file. For file-based resolvers, place the correct JWT back in the resolver directory:
# Copy from another server or regeneratensc generate creds --account <account_name>nsc push --account <account_name> --account-jwt-server-url nats://<server>1// Go - verify account is accessible2nc, _ := nats.Connect(url, nats.UserCredentials("user.creds"))3js, _ := nc.JetStream()4
5info, err := js.AccountInfo()6if err != nil {7 log.Printf("Account JetStream access failed: %v", err)8 // Account may not be resolved on this server9} else {10 log.Printf("Account OK: %d streams, %d consumers",11 info.Streams, info.Consumers)12}1// TypeScript (nats.js) - verify account access2import { connect } from "nats";3
4const nc = await connect({ servers: serverUrl, user: "user", pass: "pass" });5const jsm = await nc.jetstreamManager();6
7try {8 const info = await jsm.getAccountInfo();9 console.log(`Account OK: ${info.streams} streams`);10} catch (err) {11 console.error(`Account resolution issue: ${err.message}`);12}13
14await nc.close();Use long-lived account JWTs with automated renewal. Set account JWT expiration to a reasonable duration (90+ days) and implement automated renewal well before expiration. Monitor JWT expiration dates as part of your operational checks.
Deploy redundant account resolvers. If using a URL resolver, run multiple instances behind a load balancer. A single-point-of-failure resolver means one outage takes out account resolution for the entire deployment:
1# nats-server.conf - full resolver with caching2resolver: {3 type: full4 dir: "/data/jwt"5 allow_delete: false6 interval: "2m"7}The full resolver type syncs and caches JWTs locally, so the server can still resolve accounts even if the upstream resolver is temporarily unavailable.
Implement JWT expiration monitoring. Build or configure monitoring that alerts when account JWTs are within 30 days of expiration:
# Check all account JWT expirationsnsc list accountsnsc describe account <each_account> | grep "Expires"Audit resolver directories after maintenance. After any filesystem maintenance, migration, or cleanup on servers running file-based resolvers, verify that all expected account JWTs are present and valid.
Pin operator keys and document rotation procedures. Key rotation is necessary for security but must be coordinated across all servers and account JWTs. Document the process and test it in staging before rotating production operator keys.
JetStream assets (streams and consumers) belonging to the unresolved account are unavailable. Core NATS connections in the account may still work if the account was previously resolved and cached, but this behavior is not guaranteed. New connections authenticating to the unresolved account will fail.
Yes. A configuration reload (nats-server --signal reload or nats server config reload <server-id>) causes the server to re-resolve accounts. If the underlying issue (expired JWT, unreachable resolver) is fixed, the reload will resolve the account and recover its JetStream assets without a full server restart.
The healthz error reports the account’s public NKey (starting with A). To map it to a name, use nsc list accounts which shows both the name and public key. Alternatively, check your operator’s account configuration or the JWT itself: nsc describe account --account-key <AKEY>.
For replicated streams where other replicas are on servers that resolved the account successfully, publishes continue normally through those servers. For R1 streams or streams where all replicas are on servers with the resolution failure, publishes fail with a timeout or account error. Messages are not silently dropped — the publisher receives an error.
Yes. SERVER_014 flags when the entire JetStream subsystem on a server is unhealthy (no meta leader, not current, or recovering). SERVER_016 is more specific — one or more individual accounts failed to resolve, but the JetStream subsystem itself may otherwise be functional. A server can have a healthy JetStream subsystem overall but still fail to resolve a specific account.
With 100+ always-on audit Checks from the NATS experts, Insights helps you find and fix problems before they become costly incidents.
No alert rules to write. No dashboards to maintain.
News and content from across the community