SonarSource/sonarqube · critical · IllegalStateException

"Fail to decrypt the property " + effectiveKey + ". Please c

Error message

"Fail to decrypt the property " + effectiveKey + ". Please check your secret key."

What it means

Settings.getString reads a setting and, if the stored value is encrypted (marked by the encryption prefix), decrypts it with the configured secret key via the Encryption/AesECBCipher. Any exception during decryption is wrapped in this IllegalStateException naming the property. The library throws it because returning an undecryptable value would silently corrupt configuration.

Source

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

   * then the returned value is decrypted.
   * </p>
   *
   * @throws IllegalStateException if value is encrypted but fails to be decrypted.
   */
  @CheckForNull
  @Override
  public String getString(String key) {
    String effectiveKey = definitions.validKey(key);
    Optional<String> value = getRawString(effectiveKey);
    if (!value.isPresent()) {
      // default values cannot be encrypted, so return value as-is.
      return getDefaultValue(effectiveKey);
    }
    if (encryption.isEncrypted(value.get())) {
      try {
        return encryption.decrypt(value.get());
      } catch (Exception e) {
        throw new IllegalStateException("Fail to decrypt the property " + effectiveKey + ". Please check your secret key.", e);
      }
    }
    return value.get();
  }

  /**
   * Effective value as boolean. It is {@code false} if {@link #getString(String)}
   * does not return {@code "true"}, even if it's not a boolean representation.
   *
   * @return {@code true} if the effective value is {@code "true"}, else {@code false}.
   */
  @Override
  public boolean getBoolean(String key) {
    String value = getString(key);
    return StringUtils.isNotEmpty(value) && Boolean.parseBoolean(value);
  }

  /**

View on GitHub (pinned to 184c821202)

Solutions

  1. Copy the original sonar-secret.txt (default ~/.sonar/sonar-secret.txt or sonar.pathToSecretKey location) to the node reading the property
  2. Re-encrypt the property with the current secret key so it matches the installed key
  3. Verify file read permissions on the secret key file for the SonarQube process user
  4. Re-enter the value in clear text and re-save it via the UI/API to re-encrypt with the current key

Example fix

// before
String pwd = settings.getString("sonar.jdbc.password"); // encrypted value, wrong key
// after
// install matching sonar-secret.txt first, then
String pwd = settings.getString("sonar.jdbc.password");
Defensive patterns

Strategy: try-catch

Validate before calling

// verify secret key file exists and is readable before reading encrypted settings
java.io.File secret = new java.io.File(
    System.getProperty("user.home"), ".sonar/sonar-secret.txt");
if (!secret.canRead()) {
  throw new IllegalStateException("secret key file missing/unreadable: " + secret);
}

Try / catch

try {
  return settings.getString(key);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Fail to decrypt the property")) {
    log.error("Install the original sonar-secret.txt or re-encrypt property {}", key);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getString(key) (directly or via getInt/getBoolean/etc.) on a property whose value is encrypted but whose sonar-secret.txt is missing, unreadable, or different from the key used when encrypting.

Common situations: Migrating a SonarQube database to a new instance without copying sonar-secret.txt; regenerating the secret key; running web/CE nodes with different or absent secret keys; permission problems reading ~/.sonar/sonar-secret.txt.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/56a0087c88197d09. Report an issue: GitHub.