{"record":{"id":"d0e2facbfcfc70a4","repo":"apache/shenyu","slug":"shenyu-jwt-secretkey-is-not-configured-in-a-multi-instance","errorCode":null,"errorMessage":"shenyu.jwt.secretKey is not configured. In a multi-instance Admin cluster, each instance would generate a different key, causing token verification failures. Please explicitly configure 'shenyu.jwt.secretKey' in your configuration.","messagePattern":"shenyu\\.jwt\\.secretKey is not configured\\. In a multi-instance Admin cluster, each instance would generate a different key, causing token verification failures\\. Please explicitly configure 'shenyu\\.jwt\\.secretKey' in your configuration\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java","lineNumber":44,"sourceCode":"import org.springframework.stereotype.Component;\n\n/**\n * Jwt Properties.\n */\n@Component\n@ConfigurationProperties(prefix = \"shenyu.jwt\")\npublic class JwtProperties {\n\n    private static final Logger LOG = LoggerFactory.getLogger(JwtProperties.class);\n\n    private Long expiredSeconds = AdminConstants.THE_ONE_DAY_MILLIS_TIME;\n\n    private String secretKey;\n\n    @PostConstruct\n    private void init() {\n        if (StringUtils.isBlank(secretKey) || AdminConstants.JWT_DEFAULT_SECRET_KEY.equals(this.secretKey)) {\n            throw new IllegalStateException(\"shenyu.jwt.secretKey is not configured. \"\n                    + \"In a multi-instance Admin cluster, each instance would generate a different key, \"\n                    + \"causing token verification failures. \"\n                    + \"Please explicitly configure 'shenyu.jwt.secretKey' in your configuration.\");\n        }\n        LOG.warn(\"JWT signing key is now decoupled from user password hash. \"\n                + \"Existing sessions from previous versions will be invalidated and users will need to re-login. \"\n                + \"If rolling back, all tokens issued by this version will also become invalid.\");\n    }\n\n    /**\n     * Gets the value of expiredSeconds.\n     *\n     * @return the value of expiredSeconds\n     */\n    public Long getExpiredSeconds() {\n        return expiredSeconds;\n    }\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java#L26-L62","documentation":"At Admin startup, JwtProperties.init() (@PostConstruct) fails fast when shenyu.jwt.secretKey is blank or still set to the built-in default. This guard exists because in a multi-instance Admin cluster a per-instance random key would cause token verification failures across nodes, so an explicit shared key is mandatory.","triggerScenarios":"Starting shenyu-admin with shenyu.jwt.secretKey unset, empty, or left at AdminConstants.JWT_DEFAULT_SECRET_KEY; the IllegalStateException is thrown from the @PostConstruct init() during Spring bean initialization, so the application context fails to start.","commonSituations":"Fresh deployments using the default application.yml without setting a secret; upgrading to a version where the JWT key was decoupled from the user password hash (existing keys/default values invalidated); Docker/Kubernetes deployments missing the JWT secret env var in one replica.","solutions":["Set an explicit shenyu.jwt.secretKey (a strong random string) in application.yml, or via --shenyu.jwt.secretKey=... or the SHENYU_JWT_SECRETKEY env var, identically on every Admin instance","Generate a key (e.g. openssl rand -base64 48) and distribute the same value to all cluster nodes","If upgrading, expect prior JWT sessions to be invalidated and inform users they must re-login"],"exampleFix":"// before (application.yml)\nshenyu:\n  jwt:\n    secretKey:\n// after\nshenyu:\n  jwt:\n    secretKey: ${SHENYU_JWT_SECRET_KEY:aLongRandomSharedSecretValue}","handlingStrategy":"validation","validationCode":"if (props.getSecretKey() == null || props.getSecretKey().isBlank() || \"JWT_DEFAULT_SECRET_KEY\".equals(props.getSecretKey())) {\n    throw new IllegalArgumentException(\"shenyu.jwt.secretKey must be explicitly configured before starting admin\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set shenyu.jwt.secretKey explicitly in every environment's application.yml or via env var","Use the same key value across all admin replicas; store it in a secret manager","Fail fast in CI by asserting the config key exists in deployment manifests"],"tags":["jwt","configuration","startup","cluster"],"backgroundTag":"missing-required-config-field","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}