SonarSource/sonarqube · error · UnsupportedOperationException

Can only be called in SonarQube

Error message

Can only be called in SonarQube

What it means

SonarRuntimeImpl.getSonarQubeSide() returns the SonarQube side (scanner vs compute engine vs web server) only when the runtime was created for a SonarQube environment. When the runtime has no side (e.g. built for SonarLint/standalone, where sonarQubeSide is null) it throws UnsupportedOperationException with "Can only be called in SonarQube". The library throws this because 'side' is meaningless outside SonarQube.

Source

Thrown at sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java:67

    this.apiVersion = requireNonNull(apiVersion);
    this.product = product;
    this.sonarQubeSide = sonarQubeSide;
  }

  @Override
  public Version getApiVersion() {
    return apiVersion;
  }

  @Override
  public SonarProduct getProduct() {
    return product;
  }

  @Override
  public SonarQubeSide getSonarQubeSide() {
    if (sonarQubeSide == null) {
      throw new UnsupportedOperationException("Can only be called in SonarQube");
    }
    return sonarQubeSide;
  }

  @Override
  public SonarEdition getEdition() {
    if (sonarQubeSide == null) {
      throw new UnsupportedOperationException("Can only be called in SonarQube");
    }
    return edition;
  }

  /**
   * Create an instance for SonarQube runtime environment.
   */
  public static SonarRuntime forSonarQube(Version apiVersion, SonarQubeSide side, SonarEdition edition) {
    return new SonarRuntimeImpl(apiVersion, SonarProduct.SONARQUBE, side, edition);
  }

View on GitHub (pinned to 184c821202)

Solutions

  1. Guard the call: only invoke getSonarQubeSide() when runtime.getProduct() == SonarProduct.SONARQUBE.
  2. Branch on getProduct() and provide a fallback for SonarLint execution.
  3. If the runtime should be SonarQube, construct it with SonarRuntimeImpl.forSonarQube(...) passing a valid SonarQubeSide.

Example fix

// before
SonarQubeSide side = runtime.getSonarQubeSide();

// after
if (runtime.getProduct() == SonarProduct.SONARQUBE) {
  SonarQubeSide side = runtime.getSonarQubeSide();
} else {
  // SonarLint path: no side concept
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Java
boolean sideAvailable = runtime.getProduct() == SonarProduct.SONARQUBE;

Type guard

// Java
static boolean hasSonarQubeSide(SonarRuntime runtime) {
  return runtime.getProduct() == SonarProduct.SONARQUBE;
}

Try / catch

// Java
try {
  SonarQubeSide side = runtime.getSonarQubeSide();
} catch (UnsupportedOperationException e) {
  // SonarLint / standalone path
}

Prevention

When it happens

Trigger: Calling runtime.getSonarQubeSide() on a runtime created via SonarRuntimeImpl.forSonarLint(...) (or an equivalent standalone runtime) where sonarQubeSide is null.

Common situations: Plugin or analyzer code shared between SonarLint and SonarQube calling getSonarQubeSide() unconditionally while running inside the SonarLint IDE integration.

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


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