apache/shenyu · critical · IllegalStateException

shenyu.jwt.secretKey is not configured. In a multi-instance…

Error message

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.

What it means

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.

Solutions

  1. 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
  2. Generate a key (e.g. openssl rand -base64 48) and distribute the same value to all cluster nodes
  3. If upgrading, expect prior JWT sessions to be invalidated and inform users they must re-login

Example fix

// before (application.yml)
shenyu:
  jwt:
    secretKey:
// after
shenyu:
  jwt:
    secretKey: ${SHENYU_JWT_SECRET_KEY:aLongRandomSharedSecretValue}
Defensive patterns

Strategy: validation

Validate before calling

if (props.getSecretKey() == null || props.getSecretKey().isBlank() || "JWT_DEFAULT_SECRET_KEY".equals(props.getSecretKey())) {
    throw new IllegalArgumentException("shenyu.jwt.secretKey must be explicitly configured before starting admin");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/d0e2facbfcfc70a4. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java:44

import org.springframework.stereotype.Component;

/**
 * Jwt Properties.
 */
@Component
@ConfigurationProperties(prefix = "shenyu.jwt")
public class JwtProperties {

    private static final Logger LOG = LoggerFactory.getLogger(JwtProperties.class);

    private Long expiredSeconds = AdminConstants.THE_ONE_DAY_MILLIS_TIME;

    private String secretKey;

    @PostConstruct
    private void init() {
        if (StringUtils.isBlank(secretKey) || AdminConstants.JWT_DEFAULT_SECRET_KEY.equals(this.secretKey)) {
            throw new IllegalStateException("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.");
        }
        LOG.warn("JWT signing key is now decoupled from user password hash. "
                + "Existing sessions from previous versions will be invalidated and users will need to re-login. "
                + "If rolling back, all tokens issued by this version will also become invalid.");
    }

    /**
     * Gets the value of expiredSeconds.
     *
     * @return the value of expiredSeconds
     */
    public Long getExpiredSeconds() {
        return expiredSeconds;
    }

View on GitHub (pinned to 567142e072)