{"record":{"id":"4a10a04fa1144dd5","repo":"SonarSource/sonarqube","slug":"for-security-reasons-the-key-s-cannot-be-updat","errorCode":null,"errorMessage":"For security reasons, the key '%s' cannot be updated using this webservice. Please use the API v2","messagePattern":"For security reasons, the key '(.+?)' cannot be updated using this webservice\\. Please use the API v2","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SetAction.java","lineNumber":159,"sourceCode":"    action.createParam(PARAM_COMPONENT)\n      .setDescription(\"Component key. Only keys for projects, applications, portfolios or subportfolios are accepted.\")\n      .setExampleValue(KEY_PROJECT_EXAMPLE_001);\n  }\n\n  @Override\n  public void handle(Request request, Response response) throws Exception {\n    try (DbSession dbSession = dbClient.openSession(false)) {\n      SetRequest wsRequest = toWsRequest(request);\n      throwIfForbiddenKey(wsRequest.getKey());\n      SettingsWsSupport.validateKey(wsRequest.getKey());\n      doHandle(dbSession, wsRequest);\n    }\n    response.noContent();\n  }\n\n  private static void throwIfForbiddenKey(String key) {\n    if (FORBIDDEN_KEYS.contains(key)) {\n      throw new IllegalArgumentException(format(\"For security reasons, the key '%s' cannot be updated using this webservice. Please use the API v2\", key));\n    }\n  }\n\n  private void doHandle(DbSession dbSession, SetRequest request) {\n    Optional<EntityDto> component = searchEntity(dbSession, request);\n    String projectKey = component.map(EntityDto::getKey).orElse(null);\n    String projectName = component.map(EntityDto::getName).orElse(null);\n    String qualifier = component.map(EntityDto::getQualifier).orElse(null);\n    checkPermissions(component);\n\n    PropertyDefinition definition = propertyDefinitions.get(request.getKey());\n\n    String value;\n\n    commonChecks(request, component);\n\n    if (!request.getFieldValues().isEmpty()) {\n      value = doHandlePropertySet(dbSession, request, definition, component);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SetAction.java#L141-L177","documentation":"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.","triggerScenarios":"Calling POST api/settings/set with key= one of the FORBIDDEN_KEYS (e.g. sonar.forceAuthentication) regardless of parameters or permissions.","commonSituations":"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.","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"],"exampleFix":"// before\nPOST /api/settings/set?key=sonar.forceAuthentication&value=true\n// after\nPATCH /api/v2/governance/... (API v2) or set sonar.forceAuthentication=true in sonar.properties and restart","handlingStrategy":"validation","validationCode":"const FORBIDDEN = ['sonar.forceAuthentication'];\nif (FORBIDDEN.includes(key)) throw new Error(`Set '${key}' via API v2 or sonar.properties`);","typeGuard":"function isForbiddenKey(key) { return ['sonar.forceAuthentication'].includes(key); }","tryCatchPattern":"try { await setSetting(key, value); } catch (e) { if (/cannot be updated using this webservice/.test(e.message)) return setViaApiV2(key, value); throw e; }","preventionTips":["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"],"tags":["api","security","settings","deprecation"],"backgroundTag":"deprecated-api-usage","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}