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
- Set the property in conf/sonar.properties on the SonarQube server and restart
- Remove the key from API automation and keep only DB-managed settings there
- 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
- Classify settings as DB-managed vs boot-time before writing automation
- Maintain a deny-list of ProcessProperties keys in tooling
- When a key does not appear in api/settings/definitions, suspect it is a sonar.properties-only property
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
- For security reasons, the key
- Provided JSON is invalid
- ' ' and ' ' cannot be used at the same time as they refer…
- Address in property is not a valid address
- allowAllGroups can only be enabled when Auto-provisioning…
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)