SonarSource/sonarqube · error · IllegalArgumentException
DevOps Platform ' ' is not supported by the Remediation…
Error message
DevOps Platform '%s' is not supported by the Remediation Agent
What it means
DopPermissionValidationService.check only supports GitHub, GitLab and Azure DevOps when checking whether the Remediation Agent may access a DevOps platform. BitBucket (server) and BitBucket Cloud configurations are explicitly rejected with this IllegalArgumentException. It is a deliberate unsupported-operation guard, not a configuration corruption.
Solutions
- Filter ALM settings to GITHUB/GITLAB/AZURE_DEVOPS before invoking the check
- Use a supported DevOps platform configuration for Remediation Agent checks
- Handle IllegalArgumentException per-setting so one unsupported integration doesn't fail a batch check
Example fix
// before
for (AlmSettingDto dto : almSettings) { results.add(service.check(dto)); }
// after
for (AlmSettingDto dto : almSettings) {
if (dto.getAlm() == BITBUCKET || dto.getAlm() == BITBUCKET_CLOUD) continue;
results.add(service.check(dto));
} Defensive patterns
Strategy: type-guard
Validate before calling
Set<Alm> SUPPORTED = Set.of(GITHUB, GITLAB, AZURE_DEVOPS);
if (!SUPPORTED.contains(almSetting.getAlm())) throw new IllegalArgumentException("Remediation Agent unsupported: " + almSetting.getAlm()); Type guard
boolean isRemediationAgentSupported(AlmSettingDto dto) {
return dto != null && EnumSet.of(GITHUB, GITLAB, AZURE_DEVOPS).contains(dto.getAlm());
} Try / catch
try {
check = service.check(almSetting);
} catch (IllegalArgumentException e) {
// unsupported platform (BitBucket) — mark as N/A, not a failure
check = DopPermissionCheck.unsupported(almSetting.getAlm());
} Prevention
- Filter ALM settings by supported platforms before Remediation Agent calls
- Track feature-platform support matrix when new integrations ship
- Write tests covering each Alm enum value for any switch over alm()
When it happens
Trigger: Calling the Remediation Agent permission check (via check()/result endpoint) with an AlmSettingDto whose alm() is BITBUCKET or BITBUCKET_CLOUD.
Common situations: Tenant configured BitBucket integration and then enabled/queried the Remediation Agent; API client iterates over all ALM settings including BitBucket without filtering by supported platform.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Can not get Bitbucket user profile. HTTP code
- Can only be called in SonarQube
- Error 404. The requested Bitbucket server is unreachable.
- Error returned by Bitbucket Cloud
- Failed to count bitbucket_cloud repos for ALM setting
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/47db4d8c627a47a8.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/permission/DopPermissionValidationService.java:131
GitlabGlobalSettingsValidator gitlabGlobalSettingsValidator, AzureDevOpsValidator azureDevOpsValidator, System2 system2, Ticker cacheTicker) {
DopPermissionValidationService service = new DopPermissionValidationService(githubGlobalSettingsValidator, gitlabGlobalSettingsValidator,
azureDevOpsValidator, system2);
service.cache = buildCache(cacheTicker);
return service;
}
/**
* Checks the given DevOps Platform configuration against the Remediation Agent's required write permissions.
*
* @throws IllegalArgumentException if the configuration's platform is not supported (Bitbucket).
*/
public DopPermissionCheck check(AlmSettingDto almSetting) {
return switch (almSetting.getAlm()) {
case GITHUB -> checkGithub(almSetting);
case GITLAB -> checkGitlab(almSetting);
case AZURE_DEVOPS -> checkAzure(almSetting);
case BITBUCKET, BITBUCKET_CLOUD ->
throw new IllegalArgumentException("DevOps Platform '" + almSetting.getAlm() + "' is not supported by the Remediation Agent");
};
}
/**
* Checks several configurations in parallel and returns the results in the same order as the input. Each individual
* check is time-bounded by the ALM client's connect/read timeouts; running them concurrently keeps the total close to
* the slowest single platform. Uses a virtual thread per check rather than a fixed pool — these calls are blocking
* I/O, not CPU-bound, and there are at most a handful of supported platforms per instance, so there's no pool sizing
* to tune and no thread reuse to lose by not sharing an executor across calls. All settings must be supported
* platforms (see {@link #check(AlmSettingDto)}).
*/
public List<DopPermissionCheck> checkAll(List<AlmSettingDto> almSettings) {
return mapInParallel(almSettings, this::check);
}
/**
* Cached counterpart to {@link #check(AlmSettingDto)}. A cache hit performs no external call. Concurrent misses for
* the same configuration are coalesced into a single live check (Guava {@code Cache.get(key, Callable)} semantics).View on GitHub (pinned to 184c821202)