alibaba/nacos · error · IllegalArgumentException
Token secret key change requires restart
Error message
Token secret key change requires restart
What it means
The token secret key is the HMAC key for every issued JWT; changing it at runtime would invalidate all outstanding tokens instantly and is therefore refused. applyTokenConfig() compares the currently-applied key against the freshly-read one and throws IllegalArgumentException if they differ and a key was already applied. The only supported way to rotate the key is a full server restart so all in-memory token state is rebuilt consistently.
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java:65
}
private TokenManager getExecuteTokenManager() {
JwtTokenManager direct = tokenManager;
CachedJwtTokenManager cached = cachedTokenManager;
if (direct == null || cached == null) {
throw new IllegalStateException("Nacos auth plugin has not been initialized");
}
return configProvider.getConfig().isTokenCacheEnabled() ? cached : direct;
}
/**
* Initialize token managers once and clear cached state after relevant config changes.
*/
public synchronized void applyTokenConfig() {
NacosAuthPluginConfig current = configProvider.getConfig();
if (lastAppliedConfig != null && !Objects.equals(lastAppliedConfig.getTokenSecretKey(),
current.getTokenSecretKey())) {
throw new IllegalArgumentException("Token secret key change requires restart");
}
if (tokenManager == null) {
JwtTokenManager direct = new JwtTokenManager(configProvider);
CachedJwtTokenManager cached = new CachedJwtTokenManager(direct, configProvider);
tokenManager = direct;
cachedTokenManager = cached;
} else if (shouldClearCache(current)) {
cachedTokenManager.clear();
}
lastAppliedConfig = current;
}
private boolean shouldClearCache(NacosAuthPluginConfig current) {
return lastAppliedConfig.getTokenExpireSeconds() != current.getTokenExpireSeconds()
|| lastAppliedConfig.isTokenCacheEnabled() != current.isTokenCacheEnabled();
}
/**View on GitHub (pinned to 9b989acdf1)
Solutions
- Do not hot-swap the secret key. To rotate: set the new key in config, then restart every Nacos node in a coordinated maintenance window.
- If hit during a failed hot reload, revert the key to the previous value and restart the node.
- Distribute the same key to all cluster members before restarting to avoid cross-node token mismatch.
- After rotation, force clients to re-login (old tokens are invalid).
Example fix
// before (hot reload triggers the error) // config change event -> applyTokenConfig() -> IllegalArgumentException // after: rotate only via restart // 1. set nacos.plugin.auth.nacos.token.secret.key=<newKey> in application.properties // 2. stop all nodes // 3. start all nodes (applyTokenConfig runs once with the new key, lastAppliedConfig==null)
Defensive patterns
Strategy: validation
Validate before calling
// Reject secret-key changes at config-load time instead of letting applyTokenConfig throw.
String newKey = configProvider.getConfig().getTokenSecretKey();
String appliedKey = lastAppliedConfig == null ? null : lastAppliedConfig.getTokenSecretKey();
if (appliedKey != null && !Objects.equals(appliedKey, newKey)) {
log.error("token secret key changed at runtime; restart required. Refusing hot reload.");
// do NOT call applyTokenConfig() with the new key
} Try / catch
try {
delegate.applyTokenConfig();
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("secret key change")) {
log.error("secret key rotation requires restart; reverting");
// revert config to previous key and schedule restart
}
throw e;
} Prevention
- Never hot-swap nacos.plugin.auth.nacos.token.secret.key; rotate via a coordinated restart.
- Distribute the same key to all cluster members before restarting.
- Lock down who can edit the secret key in config management.
- After rotation, force clients to re-login.
When it happens
Trigger: Editing nacos.plugin.auth.nacos.token.secret.key in application.properties (or via a config-change event) while the server is running, then triggering a refresh that calls applyTokenConfig() a second time with the new key.
Common situations: Operator rotates the secret key via hot reload expecting tokens to keep working; an external config manager pushes a new key to a live node; clustered nodes given divergent keys one at a time.
Related errors
- 400
- the length of secret key must great than or equal 32 bytes;
- user not found!
- token invalid!
- token expired!
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/e9911393a9149d7d.
Report an issue: GitHub.