{"record":{"id":"40ee988bcfb3bba3","repo":"SonarSource/sonarqube","slug":"cannot-parse-s-s","errorCode":null,"errorMessage":"Cannot parse '%s' : %s","messagePattern":"Cannot parse '(.+?)' : (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/FilterParser.java","lineNumber":68,"sourceCode":"  public static List<Criterion> parse(String filter) {\n    return StreamSupport.stream(CRITERIA_SPLITTER.split(filter).spliterator(), false)\n      .map(FilterParser::parseCriterion)\n      .toList();\n  }\n\n  private static Criterion parseCriterion(String rawCriterion) {\n    try {\n      return Stream.of(\n          tryParsingCriterionWithoutOperator(rawCriterion),\n          tryParsingCriterionWithInOperator(rawCriterion),\n          tryParsingCriterionWithComparisonOperator(rawCriterion)\n        )\n        .filter(Optional::isPresent)\n        .map(Optional::get)\n        .findFirst()\n        .orElseThrow(() -> new IllegalArgumentException(\"Criterion is invalid\"));\n    } catch (Exception e) {\n      throw new IllegalArgumentException(String.format(\"Cannot parse '%s' : %s\", rawCriterion, e.getMessage()), e);\n    }\n  }\n\n  private static Optional<Criterion> tryParsingCriterionWithoutOperator(String criterion) {\n    Matcher matcher = PATTERN_WITHOUT_OPERATOR.matcher(criterion);\n    if (!matcher.matches()) {\n      return Optional.empty();\n    }\n    Criterion.Builder builder = new Criterion.Builder();\n    builder.setKey(matcher.group(1));\n    return Optional.of(builder.build());\n  }\n\n  private static Optional<Criterion> tryParsingCriterionWithComparisonOperator(String criterion) {\n    Matcher matcher = PATTERN_WITH_COMPARISON_OPERATOR.matcher(criterion);\n    if (!matcher.matches()) {\n      return Optional.empty();\n    }","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/FilterParser.java#L50-L86","documentation":"The SonarQube web API's filter/query parser (used by WS endpoints that accept criteria strings like 'languages = java') wraps any failure while parsing a single criterion into this IllegalArgumentException, preserving the raw criterion text and the underlying parse exception message. It is thrown from parseCriterion when none of the known criterion patterns (with or without an operator) match or an inner parser fails.","triggerScenarios":"Passing a malformed criterion string to a Web API that accepts filter criteria (e.g. api/projects/search with a 'criteria'-style parameter); the criterion string does not match the expected '<key> <operator> <value>' grammar (typo, missing operator, unquoted spaces, invalid operator).","commonSituations":"Copy-pasted filter strings with extra whitespace or smart quotes; custom dashboards or scripts building criteria by string concatenation; API version changes that added/renamed operators leaving old clients sending unsupported syntax.","solutions":["Inspect the raw criterion echoed in the message and fix it to match '<key> <operator> <value>' (e.g. 'languages = java', 'rating > 3').","Check for whitespace/encoding problems (trailing spaces, URL-encoding, quotes) in the criterion string.","Validate each criterion against the documented operator set for the endpoint before sending.","Upgrade/align client code with the SonarQube version's FilterParser grammar if syntax changed between versions."],"exampleFix":"// before\nString criteria = \"languages: java\"; // invalid separator\n// after\nString criteria = \"languages = java\"; // '<key> <operator> <value>'","handlingStrategy":"validation","validationCode":"String VALID = \"^(?<key>[a-zA-Z_]+)\\\\s*(?<op>=|!=|<=|>=|<|>|IN)\\\\s*(?<value>.+)$\";\nif (!rawCriterion.matches(VALID)) {\n  throw new IllegalArgumentException(\"Invalid criterion (expected '<key> <operator> <value>'): \" + rawCriterion);\n}","typeGuard":null,"tryCatchPattern":"try {\n  ws.search(criteria);\n} catch (SonarError e) {\n  if (e.getMessage().startsWith(\"Cannot parse '\")) {\n    log.warn(\"Bad criterion '{}': fix syntax\", criteria);\n  } else throw e;\n}","preventionTips":["Build criteria programmatically from typed key/operator/value triples instead of raw strings.","URL-encode criteria properly when sending over HTTP.","Test filter strings against the target SonarQube version's grammar."],"tags":["java","sonarqube","web-api","input-parsing"],"backgroundTag":"invalid-argument-format","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"}