{"record":{"id":"e9b9973e0a6f54f6","repo":"alibaba/nacos","slug":"nacos-auth-plugin-has-not-been-initialized","errorCode":null,"errorMessage":"Nacos auth plugin has not been initialized","messagePattern":"Nacos auth plugin has not been initialized","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java","lineNumber":53,"sourceCode":"public class TokenManagerDelegate implements TokenManager {\n    \n    private final NacosAuthPluginConfigProvider configProvider;\n    \n    private volatile JwtTokenManager tokenManager;\n    \n    private volatile CachedJwtTokenManager cachedTokenManager;\n    \n    private NacosAuthPluginConfig lastAppliedConfig;\n    \n    public TokenManagerDelegate(NacosAuthPluginConfigProvider configProvider) {\n        this.configProvider = configProvider;\n    }\n    \n    private TokenManager getExecuteTokenManager() {\n        JwtTokenManager direct = tokenManager;\n        CachedJwtTokenManager cached = cachedTokenManager;\n        if (direct == null || cached == null) {\n            throw new IllegalStateException(\"Nacos auth plugin has not been initialized\");\n        }\n        return configProvider.getConfig().isTokenCacheEnabled() ? cached : direct;\n    }\n    \n    /**\n     * Initialize token managers once and clear cached state after relevant config changes.\n     */\n    public synchronized void applyTokenConfig() {\n        NacosAuthPluginConfig current = configProvider.getConfig();\n        if (lastAppliedConfig != null && !Objects.equals(lastAppliedConfig.getTokenSecretKey(),\n            current.getTokenSecretKey())) {\n            throw new IllegalArgumentException(\"Token secret key change requires restart\");\n        }\n        if (tokenManager == null) {\n            JwtTokenManager direct = new JwtTokenManager(configProvider);\n            CachedJwtTokenManager cached = new CachedJwtTokenManager(direct, configProvider);\n            tokenManager = direct;\n            cachedTokenManager = cached;","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.java#L35-L71","documentation":"TokenManagerDelegate lazily resolves its real delegate via getExecuteTokenManager(), which requires applyTokenConfig() to have run at least once to populate both tokenManager and cachedTokenManager. If any createToken/parseToken/validateToken call reaches the delegate before that initialization completes, it throws IllegalStateException. This is a lifecycle defect: a token operation arrived before the auth plugin finished bootstrapping.","triggerScenarios":"A login or token-validation request arrives during server startup before the auth plugin's applyTokenConfig() init hook fires; a unit test new'd TokenManagerDelegate directly without calling applyTokenConfig(); a Spring bean-ordering problem where the delegate is injected and used before its initializer bean runs.","commonSituations":"Early client traffic during a rolling restart hitting a node whose auth plugin has not finished init; custom integration tests that construct the delegate manually; bean wiring error omitting the config-init bean.","solutions":["Ensure applyTokenConfig() is invoked during plugin startup (e.g. in a @PostConstruct or the auth plugin init hook) before any token API is exposed.","In tests, call delegate.applyTokenConfig() right after constructing it.","Delay accepting auth-bound traffic until the plugin reports ready; check server startup logs for the auth-plugin-initialized marker.","If seen in production, restart the affected node so the init hook runs cleanly."],"exampleFix":"// before\nTokenManagerDelegate delegate = new TokenManagerDelegate(configProvider);\nString token = delegate.createToken(\"alice\"); // throws IllegalStateException\n\n// after\nTokenManagerDelegate delegate = new TokenManagerDelegate(configProvider);\ndelegate.applyTokenConfig(); // must run first\nString token = delegate.createToken(\"alice\");","handlingStrategy":"validation","validationCode":"// Ensure the delegate is initialized before any token operation.\nTokenManagerDelegate delegate = new TokenManagerDelegate(configProvider);\ndelegate.applyTokenConfig(); // MUST run before createToken/parseToken/validateToken\n// If you cannot call it directly, guard usage:\ntry {\n    delegate.parseToken(token);\n} catch (IllegalStateException e) {\n    log.error(\"auth plugin not initialized; init ordering bug\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    nacosUser = tokenManager.parseToken(token);\n} catch (IllegalStateException e) {\n    // plugin not initialized yet -> fail closed, do not serve authed traffic\n    log.error(\"auth plugin not initialized: {}\", e.getMessage());\n    throw new ServiceUnavailableException(\"authentication service is starting\");\n}","preventionTips":["Call applyTokenConfig() in the auth plugin's @PostConstruct before exposing token APIs.","In tests, always invoke applyTokenConfig() right after constructing the delegate.","Delay auth-bound traffic until startup completes.","Treat this as fail-closed: never bypass auth when uninitialized."],"tags":["auth","token","jwt","lifecycle","initialization"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}