{"record":{"id":"586a2f84005b26b1","repo":"SonarSource/sonarqube","slug":"quality-gate-unable-to-parse-value-s-to-compar","errorCode":null,"errorMessage":"Quality Gate: Unable to parse value '%s' to compare against %s","messagePattern":"Quality Gate: Unable to parse value '(.+?)' to compare against (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluator.java","lineNumber":65,"sourceCode":"\n    Comparable measureComparable = parseMeasure(measure);\n    if (measureComparable == null) {\n      return new EvaluationResult(Measure.Level.OK, null);\n    }\n\n    return evaluateCondition(condition, measureComparable)\n      .orElseGet(() -> new EvaluationResult(Measure.Level.OK, measureComparable));\n  }\n\n  private static Optional<EvaluationResult> evaluateCondition(Condition condition, Comparable<?> measureComparable) {\n    try {\n      Comparable conditionComparable = parseConditionValue(condition.getMetric(), condition.getErrorThreshold());\n      if (doesReachThresholds(measureComparable, conditionComparable, condition)) {\n        return of(new EvaluationResult(Measure.Level.ERROR, measureComparable));\n      }\n      return Optional.empty();\n    } catch (NumberFormatException badValueFormat) {\n      throw new IllegalArgumentException(String.format(\n        \"Quality Gate: Unable to parse value '%s' to compare against %s\",\n        condition.getErrorThreshold(), condition.getMetric().getName()));\n    }\n  }\n\n  private static boolean doesReachThresholds(Comparable measureValue, Comparable criteriaValue, Condition condition) {\n    int comparison = measureValue.compareTo(criteriaValue);\n    switch (condition.getOperator()) {\n      case GREATER_THAN:\n        return comparison > 0;\n      case LESS_THAN:\n        return comparison < 0;\n      default:\n        throw new IllegalArgumentException(String.format(\"Unsupported operator '%s'\", condition.getOperator()));\n    }\n  }\n\n  private static Comparable parseConditionValue(Metric metric, String value) {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluator.java#L47-L83","documentation":"ConditionEvaluator.evaluateCondition() compares a measure against a Quality Gate condition's error threshold. parseConditionValue() throws NumberFormatException when either the threshold or the measure is not a parseable number; the catch block rethrows it as IllegalArgumentException 'Quality Gate: Unable to parse value ...'. The message reports the error threshold and metric name that could not be compared numerically.","triggerScenarios":"A Quality Gate condition on a numeric metric (e.g. coverage, lines) has an error threshold that is not a plain number — like '85%', '1.5h', empty string, or a comma decimal '99,9' — while evaluating conditions in computeQualityGateSteps for a project's measures.","commonSituations":"Admins typing thresholds with units ('80%') or locale commas in the Quality Gate editor, conditions created via API/web service with malformed values, or string/duration metrics used with numeric comparison operators.","solutions":["Edit the Quality Gate condition and set the error threshold to a plain decimal number (e.g. '85' not '85%', use '.' not ',')","Check the metric: conditions only make sense on numeric metrics; move the condition to a numeric metric (e.g. coverage, duplicated_lines_density)","If set via API, POST numeric thresholds without units or thousands separators"],"exampleFix":"// before: threshold with unit / comma decimal\n\"coverage\": \"85%\"        // fails\n\"new_violations\": \"1,5\"  // fails\n// after\n\"coverage\": \"85\"\n\"new_violations\": \"1.5\"","handlingStrategy":"validation","validationCode":"static boolean isNumericThreshold(String threshold) {\n  if (threshold == null || threshold.isBlank()) return false;\n  try { Double.parseDouble(threshold.trim()); return true; } catch (NumberFormatException e) { return false; }\n}\n// before creating a condition: if (!isNumericThreshold(\"85\")) strip units/locale commas;","typeGuard":"static Optional<Double> asDouble(String s) {\n  try { return Optional.of(Double.parseDouble(s.trim())); } catch (NumberFormatException | NullPointerException e) { return Optional.empty(); }\n}","tryCatchPattern":"try {\n  Optional<EvaluationResult> r = evaluator.evaluate(condition, measure);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Quality Gate: Unable to parse value\")) {\n    throw new ConfigurationException(\"Fix threshold: plain decimal, no % or comma: \" + condition.getErrorThreshold());\n  }\n  throw e;\n}","preventionTips":["Enter Quality Gate thresholds as plain decimals: '85' not '85%'","Use '.' as decimal separator regardless of server locale","Only attach conditions to numeric metrics","When creating conditions via api/qualitygates, validate the value with parseDouble first"],"tags":["quality-gate","threshold","numberformat"],"backgroundTag":"invalid-config-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}