{"record":{"id":"0635bac3fb95fd7f","repo":"google/tsunami-security-scanner","slug":"string-s-is-neither-a-discrete-string-nor-a-version-range","errorCode":null,"errorMessage":"String '%s' is neither a discrete string nor a version range.","messagePattern":"String '(.+?)' is neither a discrete string nor a version range\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/com/google/tsunami/common/version/VersionSet.java","lineNumber":67,"sourceCode":"      return this;\n    }\n\n    public abstract VersionSet build();\n  }\n\n  public static VersionSet parse(ImmutableList<String> versionAndRangesList) {\n    checkNotNull(versionAndRangesList);\n    checkArgument(!versionAndRangesList.isEmpty(), \"Versions and ranges list cannot be empty.\");\n\n    VersionSet.Builder versionSetBuilder = VersionSet.builder();\n\n    for (String versionOrRangeString : versionAndRangesList) {\n      if (isDiscreteVersion(versionOrRangeString)) {\n        versionSetBuilder.addVersion(Version.fromString(versionOrRangeString));\n      } else if (VersionRange.isValidVersionRange(versionOrRangeString)) {\n        versionSetBuilder.addVersionRange(VersionRange.parse(versionOrRangeString));\n      } else {\n        throw new IllegalArgumentException(\n            String.format(\n                \"String '%s' is neither a discrete string nor a version range.\",\n                versionOrRangeString));\n      }\n    }\n\n    return versionSetBuilder.build();\n  }\n\n  private static boolean isDiscreteVersion(String versionOrRangeString) {\n    return CharMatcher.anyOf(\"[()], \").matchesNoneOf(versionOrRangeString);\n  }\n}\n","sourceCodeStart":49,"sourceCodeEnd":81,"githubUrl":"https://github.com/google/tsunami-security-scanner/blob/363ba87b3543f8ae8e4304d3416818f03da7f262/common/src/main/java/com/google/tsunami/common/version/VersionSet.java#L49-L81","documentation":"VersionSet.parse accepts a list of strings that must each be either a discrete version (parsed via Version.fromString) or a valid version range (parsed via VersionRange.parse). A string that fails both checks is rejected with this IllegalArgumentException.","triggerScenarios":"Calling VersionSet.parse with any element that is neither a parseable version nor a string passing VersionRange.isValidVersionRange, e.g. \"abc\", \"1.0;2.0\", or a malformed range like \"[1.0,\".","commonSituations":"Typos in vulnerability-configuration version lists, semicolon- or space-separated versions pasted from other tools, or versions with invalid characters that fail Version.fromString.","solutions":["Fix the offending string to be a valid version like \"1.2.3\" or a valid range like \"[1.0,2.0)\".","Pre-validate each element with Version.fromString (in try/catch) and VersionRange.isValidVersionRange before calling parse.","Check the log/output for the exact string quoted in the message and correct it in the config."],"exampleFix":"// before\nVersionSet.parse(Arrays.asList(\"1.0.0\", \"1.0;2.0\"));\n// after\nVersionSet.parse(Arrays.asList(\"1.0.0\", \"[1.0,2.0]\"));","handlingStrategy":"validation","validationCode":"boolean ok(String s) { try { Version.fromString(s); return true; } catch (IllegalArgumentException e) { return VersionRange.isValidVersionRange(s); } }","typeGuard":null,"tryCatchPattern":"try { VersionSet.parse(list); } catch (IllegalArgumentException e) { log.error(\"Bad version element: {}\", e.getMessage()); }","preventionTips":["Validate each element as version-or-range before calling VersionSet.parse.","Keep separators out of version strings (no ';' or spaces).","Check the offending string quoted in the message and fix it in config."],"tags":["version-set","parsing","illegal-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"363ba87b3543f8ae8e4304d3416818f03da7f262","analyzedAt":"2026-09-13T01:50:53.990Z","contentChangedAt":"2026-09-13T01:50:53.990Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}