SonarSource/sonarqube · error · IllegalStateException

Metric ' ' is not supported

Error message

Metric '%s' is not supported

What it means

UnitTestMeasuresStep builds a Measure for a given unit-test metric key on file-level components. The switch over metricKey only supports known test metrics (tests, test_failures, test_errors, skipped_tests, test_execution_time, test_success_density); an unknown key reaching the default branch throws an IllegalStateException.

Solutions

  1. Log/inspect the offending metricKey to identify which plugin or analyzer emitted it
  2. Update or remove the plugin introducing the unsupported metric
  3. Align analyzer and SonarQube server versions so supported metric keys match
  4. If it is a valid new metric, it must be added to the switch in UnitTestMeasuresStep (code change/upgrade)
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> SUPPORTED = Set.of(
  "tests", "test_failures", "test_errors", "skipped_tests",
  "test_execution_time", "test_success_density");
boolean isSupportedTestMetric(String metricKey) { return SUPPORTED.contains(metricKey); }

Try / catch

try {
  Optional<Measure> m = createMeasure(context, metricKey, counters);
} catch (IllegalStateException e) {
  LOGGER.warn("Skipping unsupported unit-test metric: {}", metricKey, e);
}

Prevention

When it happens

Trigger: createMeasure is invoked with a metricKey from the report/measure context that is not one of the supported unit-test metric keys, e.g. a metric fed by an analyzer or plugin that this step does not handle.

Common situations: A plugin registers a new unit-test metric not handled by this CE step; analyzer/server version skew introducing a new metric key; misconfigured report containing unexpected metric keys.

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/0f07097fd9f80680. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/UnitTestMeasuresStep.java:96

    @Override
    public Optional<Measure> createMeasure(UnitTestsCounter counter, CreateMeasureContext context) {
      String metricKey = context.getMetric().getKey();
      Component leaf = counter.getLeaf();
      switch (metricKey) {
        case TESTS_KEY:
          return createIntMeasure(context.getComponent(), leaf, counter.testsCounter.getValue());
        case TEST_ERRORS_KEY:
          return createIntMeasure(context.getComponent(), leaf, counter.testsErrorsCounter.getValue());
        case TEST_FAILURES_KEY:
          return createIntMeasure(context.getComponent(), leaf, counter.testsFailuresCounter.getValue());
        case SKIPPED_TESTS_KEY:
          return createIntMeasure(context.getComponent(), leaf, counter.skippedTestsCounter.getValue());
        case TEST_EXECUTION_TIME_KEY:
          return createLongMeasure(context.getComponent(), leaf, counter.testExecutionTimeCounter.getValue());
        case TEST_SUCCESS_DENSITY_KEY:
          return createDensityMeasure(counter, context.getMetric().getDecimalScale());
        default:
          throw new IllegalStateException(String.format("Metric '%s' is not supported", metricKey));
      }
    }

    private static Optional<Measure> createIntMeasure(Component currentComponent, Component leafComponent, Optional<Integer> metricValue) {
      if (metricValue.isPresent() && leafComponent.getType().isDeeperThan(currentComponent.getType())) {
        return Optional.of(Measure.newMeasureBuilder().create(metricValue.get()));
      }
      return Optional.empty();
    }

    private static Optional<Measure> createLongMeasure(Component currentComponent, Component leafComponent, Optional<Long> metricValue) {
      if (metricValue.isPresent() && leafComponent.getType().isDeeperThan(currentComponent.getType())) {
        return Optional.of(Measure.newMeasureBuilder().create(metricValue.get()));
      }
      return Optional.empty();
    }

    private static Optional<Measure> createDensityMeasure(UnitTestsCounter counter, int decimalScale) {

View on GitHub (pinned to 184c821202)