SonarSource/sonarqube · error · IllegalArgumentException

Setting ' ' can only be used in sonar.properties

Error message

Setting '%s' can only be used in sonar.properties

What it means

Some properties (ProcessProperties.Property enum values) are boot-time settings that can only be defined in sonar.properties on the server; SettingsWsSupport.validateKey rejects any attempt to store them via the web service settings API. Throwing happens before any read/write, returning 400 to the caller.

Solutions

  1. Set the property in conf/sonar.properties on the SonarQube server and restart
  2. Remove the key from API automation and keep only DB-managed settings there
  3. Rename the key if it was a typo colliding with a reserved ProcessProperties key

Example fix

// before
POST /api/settings/set?key=sonar.web.port&value=9001
// after
# conf/sonar.properties
sonar.web.port=9001   (then restart server)
Defensive patterns

Strategy: validation

Validate before calling

const PROCESS_PROPERTY_KEYS = new Set(['sonar.web.port','sonar.path.data' /* ...ProcessProperties keys */]);
if (PROCESS_PROPERTY_KEYS.has(key.toLowerCase())) throw new Error(`'${key}' belongs in sonar.properties`);

Type guard

function isProcessProperty(key) { return processPropertyKeys.some(k => k.toLowerCase() === key.toLowerCase()); }

Try / catch

try { await setSetting(key, v); } catch (e) { if (/can only be used in sonar\.properties/.test(e.message)) { applyToServerProperties(key, v); return; } throw e; }

Prevention

When it happens

Trigger: Calling api/settings/set (or api/settings/values) with key equal (case-insensitively) to any ProcessProperties.Property key, e.g. sonar.web.port, sonar.path.data, sonar.cluster.*.

Common situations: Automation trying to move ALL sonar.* configuration into DB-stored settings; operators confusing runtime settings with bootstrap properties; copy-pasting sonar.properties content into the UI.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java:53

@ServerSide
public class SettingsWsSupport {
  public static final String DOT_SECURED = ".secured";
  @VisibleForTesting
  static final Set<String> ADMIN_ONLY_SETTINGS = Set.of("sonar.auth.bitbucket.workspaces", "sonar.auth.github.organizations");

  private final UserSession userSession;

  public SettingsWsSupport(UserSession userSession) {
    this.userSession = userSession;
  }

  static void validateKey(String key) {
    stream(ProcessProperties.Property.values())
      .filter(property -> property.getKey().equalsIgnoreCase(key))
      .findFirst()
      .ifPresent(property -> {
        throw new IllegalArgumentException(format("Setting '%s' can only be used in sonar.properties", key));
      });
  }

  boolean isVisible(String key, Optional<EntityDto> component) {
    if (isAdmin(component)) {
      return true;
    }
    return hasPermission(GlobalPermission.SCAN, ProjectPermission.SCAN, component) || !isProtected(key);
  }

  private boolean isAdmin(Optional<EntityDto> component) {
    return userSession.isSystemAdministrator() || hasPermission(GlobalPermission.ADMINISTER, ADMIN, component);
  }

  private static boolean isProtected(String key) {
    return isSecured(key) || isAdminOnly(key);
  }

View on GitHub (pinned to 184c821202)