SonarSource/sonarqube · error · IllegalArgumentException
For security reasons, the key
Error message
For security reasons, the key '%s' cannot be updated using this webservice. Please use the API v2
What it means
SonarQube's settings web service (api/settings/set) refuses to update a small set of security-sensitive properties whose keys are in FORBIDDEN_KEYS (e.g. sonar.forceAuthentication). These must be managed via the v2 REST API for auditability. throwIfForbiddenKey runs before any persistence in SetAction.handle, so the request is rejected with 400 before the setting is touched.
Solutions
- Migrate the call to the API v2 endpoint (e.g. PATCH /api/v2/settings or the dedicated governance endpoint) for that key
- Remove the key from automation and set it once via sonar.properties on the server (restart required)
- Check the key against FORBIDDEN_KEYS in SetAction.java before calling the API
Example fix
// before POST /api/settings/set?key=sonar.forceAuthentication&value=true // after PATCH /api/v2/governance/... (API v2) or set sonar.forceAuthentication=true in sonar.properties and restart
Defensive patterns
Strategy: validation
Validate before calling
const FORBIDDEN = ['sonar.forceAuthentication'];
if (FORBIDDEN.includes(key)) throw new Error(`Set '${key}' via API v2 or sonar.properties`); Type guard
function isForbiddenKey(key) { return ['sonar.forceAuthentication'].includes(key); } Try / catch
try { await setSetting(key, value); } catch (e) { if (/cannot be updated using this webservice/.test(e.message)) return setViaApiV2(key, value); throw e; } Prevention
- Check the FORBIDDEN_KEYS list in SetAction.java before automating a setting
- Use API v2 for security/governance settings
- Keep boot-time properties in sonar.properties, not the settings API
When it happens
Trigger: Calling POST api/settings/set with key= one of the FORBIDDEN_KEYS (e.g. sonar.forceAuthentication) regardless of parameters or permissions.
Common situations: Legacy automation scripts, Terraform/Ansible playbooks, or CI jobs written against the old v1 settings API keep setting security properties; environments migrating from older SonarQube versions to ones where these keys were locked down.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- Provided JSON is invalid
- ' ' and ' ' cannot be used at the same time as they refer…
- Setting ' ' can only be used in sonar.properties
- Address contains invalid character: 0x%02x
- Authentication is not enforced, and permissions assigned to…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/4a10a04fa1144dd5.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SetAction.java:159
action.createParam(PARAM_COMPONENT)
.setDescription("Component key. Only keys for projects, applications, portfolios or subportfolios are accepted.")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
}
@Override
public void handle(Request request, Response response) throws Exception {
try (DbSession dbSession = dbClient.openSession(false)) {
SetRequest wsRequest = toWsRequest(request);
throwIfForbiddenKey(wsRequest.getKey());
SettingsWsSupport.validateKey(wsRequest.getKey());
doHandle(dbSession, wsRequest);
}
response.noContent();
}
private static void throwIfForbiddenKey(String key) {
if (FORBIDDEN_KEYS.contains(key)) {
throw new IllegalArgumentException(format("For security reasons, the key '%s' cannot be updated using this webservice. Please use the API v2", key));
}
}
private void doHandle(DbSession dbSession, SetRequest request) {
Optional<EntityDto> component = searchEntity(dbSession, request);
String projectKey = component.map(EntityDto::getKey).orElse(null);
String projectName = component.map(EntityDto::getName).orElse(null);
String qualifier = component.map(EntityDto::getQualifier).orElse(null);
checkPermissions(component);
PropertyDefinition definition = propertyDefinitions.get(request.getKey());
String value;
commonChecks(request, component);
if (!request.getFieldValues().isEmpty()) {
value = doHandlePropertySet(dbSession, request, definition, component);View on GitHub (pinned to 184c821202)