SonarSource/sonarqube · critical · IllegalStateException

"Secret key not found. Please set the property " + ENCRYPTIO

Error message

"Secret key not found. Please set the property " + ENCRYPTION_SECRET_KEY_PATH

What it means

AesCipher.loadSecretFileFromFile throws this IllegalStateException when the configured path to the AES secret key is null, empty or blank. SonarQube uses this secret key file to encrypt/decrypt secure settings, so without it secure configuration cannot be processed. The message points the user to the ENCRYPTION_SECRET_KEY_PATH property (sonar.secretKeyPath).

Source

Thrown at sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/AesCipher.java:70

   * This method checks the existence of the file, but not the validity of the contained key.
   */
  boolean hasSecretKey() {
    String path = getPathToSecretKey();
    if (StringUtils.isNotBlank(path)) {
      File file = new File(path);
      return file.exists() && file.isFile();
    }
    return false;
  }

  protected Key loadSecretFile() throws IOException {
    String path = getPathToSecretKey();
    return loadSecretFileFromFile(path);
  }

  Key loadSecretFileFromFile(@Nullable String path) throws IOException {
    if (StringUtils.isBlank(path)) {
      throw new IllegalStateException("Secret key not found. Please set the property " + ENCRYPTION_SECRET_KEY_PATH);
    }
    File file = new File(path);
    if (!file.exists() || !file.isFile()) {
      throw new IllegalStateException("The property " + ENCRYPTION_SECRET_KEY_PATH + " does not link to a valid file: " + path);
    }
    String s = FileUtils.readFileToString(file, UTF_8);
    if (StringUtils.isBlank(s)) {
      throw new IllegalStateException("No secret key in the file: " + path);
    }
    return new SecretKeySpec(Base64.decodeBase64(StringUtils.trim(s)), CRYPTO_KEY);
  }

  String generateRandomSecretKey() {
    try {
      KeyGenerator keyGen = KeyGenerator.getInstance(CRYPTO_KEY);
      keyGen.init(KEY_SIZE_IN_BITS, new SecureRandom());
      SecretKey secretKey = keyGen.generateKey();
      return Base64.encodeBase64String(secretKey.getEncoded());

View on GitHub (pinned to 184c821202)

Solutions

  1. Generate and place a secret key file (e.g. run the SonarQube encryption/secret-key generation) at the location expected by sonar.secretKeyPath.
  2. Set sonar.secretKeyPath in sonar.properties to point at the existing Base64 secret key file.
  3. If migrating, copy the original secret.key file from the old installation to the new server's configured path.
  4. Verify the property name and value are correct (no blank/whitespace value).

Example fix

// sonar.properties
// before: property missing -> IllegalStateException
// after:
sonar.secretKeyPath=/opt/sonarqube/conf/secret.key
Defensive patterns

Strategy: validation

Validate before calling

String path = settings.get("sonar.secretKeyPath");
if (path == null || path.isBlank()) {
  throw new IllegalStateException("sonar.secretKeyPath must be set to use encrypted settings");
}

Try / catch

try {
  Key key = aesCipher.loadSecretFile();
} catch (IllegalStateException e) {
  LOG.error("Configure sonar.secretKeyPath: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling loadSecretFile() (or loadSecretFileFromFile with a blank path) while the sonar.secretKeyPath property is not set and no default location (~/.sonar/secret.key) contains a key.

Common situations: Fresh SonarQube installation where encryption was never initialized; trying to read encrypted settings (sonar.token, JDBC password) without running the secret key generation; migrating a server without copying the secret key file; property typo so the path resolves to blank.

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 SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/39d06bb548413b76. Report an issue: GitHub.