SonarSource/sonarqube · error · IllegalArgumentException

The rating grid is incorrect. Expected something similar to…

Error message

The rating grid is incorrect. Expected something similar to '" + RATING_GRID_DEF_VALUES + "' and got '" + config.get(RATING_GRID).orElse("") + "'

What it means

DebtRatingGrid parses the RATING_GRID configuration (comma-separated percentage bounds for the 5 reliability/security ratings) into doubles and builds rating bounds. If parsing or bound building fails (wrong number of values, non-numeric, non-increasing bounds), it throws IllegalArgumentException echoing the expected default and the received value.

Solutions

  1. Set the rating grid to exactly 4 comma-separated ascending decimals, e.g. the default '0.05,0.1,0.2,0.5'.
  2. Use dots as decimal separators (parsing is via Double.parseDouble, not locale-aware).
  3. Remove the setting to fall back to RATING_GRID_DEF_VALUES if the custom grid is not needed.
  4. Validate the value in a settings UI/import before applying it.

Example fix

// before
sonar.technicaldebt.ratingGrid=0,05,0,10,0,20,0,50
// after
sonar.technicaldebt.ratingGrid=0.05,0.1,0.2,0.5
Defensive patterns

Strategy: validation

Validate before calling

String grid = config.get(RATING_GRID).orElse("");
String[] parts = grid.split(",");
if (parts.length != 4) throw new IllegalArgumentException("RATING_GRID must have 4 values");
double prev = -1;
for (String p : parts) { double v = Double.parseDouble(p.trim()); if (v <= prev) throw new IllegalArgumentException("RATING_GRID must be ascending"); prev = v; }

Try / catch

try { new DebtRatingGrid(config); } catch (IllegalArgumentException e) { log.error("Bad rating grid '{}', using default", config.get(RATING_GRID).orElse("")); grid = DebtRatingGrid.DEFAULT; }

Prevention

When it happens

Trigger: sonar.technicaldebt.ratingGrid set to a value that is not exactly 4 comma-separated ascending numeric percentages, e.g. '0.05,0.15' or 'a,b,c,d'.

Common situations: Admin editing the rating grid in Administration > General Settings with typos or wrong separators; locale decimal commas; copying a grid from docs of a different version.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java:52

import static org.sonar.server.measure.Rating.C;
import static org.sonar.server.measure.Rating.D;
import static org.sonar.server.measure.Rating.E;

public final class DebtRatingGrid {

  private final double[] gridValues;
  private final EnumMap<Rating, Bounds> ratingBounds;

  public DebtRatingGrid(Configuration config) {
    try {
      String[] grades = config.getStringArray(RATING_GRID);
      gridValues = new double[4];
      for (int i = 0; i < 4; i++) {
        gridValues[i] = Double.parseDouble(grades[i]);
      }
      this.ratingBounds = buildRatingBounds(gridValues);
    } catch (Exception e) {
      throw new IllegalArgumentException("The rating grid is incorrect. Expected something similar to '"
        + RATING_GRID_DEF_VALUES + "' and got '" + config.get(RATING_GRID).orElse("") + "'", e);
    }
  }

  public DebtRatingGrid(double[] gridValues) {
    this.gridValues = Arrays.copyOf(gridValues, gridValues.length);
    this.ratingBounds = buildRatingBounds(gridValues);
  }

  private static EnumMap<Rating, Bounds> buildRatingBounds(double[] gridValues) {
    checkState(gridValues.length == 4, "Rating grid should contains 4 values");
    EnumMap<Rating, Bounds> ratingBounds = new EnumMap<>(Rating.class);
    ratingBounds.put(A, new Bounds(gridValues[0]));
    ratingBounds.put(B, new Bounds(gridValues[0], gridValues[1]));
    ratingBounds.put(C, new Bounds(gridValues[1], gridValues[2]));
    ratingBounds.put(D, new Bounds(gridValues[2], gridValues[3]));
    ratingBounds.put(E, new Bounds(gridValues[3], Double.MAX_VALUE));
    return ratingBounds;

View on GitHub (pinned to 184c821202)