{"record":{"id":"7a1a108fd712765d","repo":"spring-projects/spring-boot","slug":"value-must-contain-a-well-formed-version-number","errorCode":null,"errorMessage":"'value' must contain a well formed version number [{}]","messagePattern":"'value' must contain a well formed version number \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ApiVersion.java","lineNumber":137,"sourceCode":"\n\t/**\n\t * Factory method to parse a string into an {@link ApiVersion} instance.\n\t * @param value the value to parse.\n\t * @return the corresponding {@link ApiVersion}\n\t * @throws IllegalArgumentException if the value could not be parsed\n\t */\n\tpublic static ApiVersion parse(String value) {\n\t\tAssert.hasText(value, \"'value' must not be empty\");\n\t\tMatcher matcher = PATTERN.matcher(value);\n\t\tAssert.isTrue(matcher.matches(),\n\t\t\t\t() -> \"'value' [%s] must contain a well formed version number\".formatted(value));\n\t\ttry {\n\t\t\tint major = Integer.parseInt(matcher.group(1));\n\t\t\tint minor = Integer.parseInt(matcher.group(2));\n\t\t\treturn new ApiVersion(major, minor);\n\t\t}\n\t\tcatch (NumberFormatException ex) {\n\t\t\tthrow new IllegalArgumentException(\"'value' must contain a well formed version number [\" + value + \"]\", ex);\n\t\t}\n\t}\n\n\tpublic static ApiVersion of(int major, int minor) {\n\t\treturn new ApiVersion(major, minor);\n\t}\n\n\t@Override\n\tpublic int compareTo(ApiVersion other) {\n\t\treturn COMPARATOR.compare(this, other);\n\t}\n\n}\n","sourceCodeStart":119,"sourceCodeEnd":151,"githubUrl":"https://github.com/spring-projects/spring-boot/blob/270dfe353fb830fd69b823a8a859287ff103854b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ApiVersion.java#L119-L151","documentation":"ApiVersion.parse parses a 'major.minor' version string. First it asserts the regex PATTERN matches, then parses both captured groups as integers. NumberFormatException (e.g. integer overflow on extremely large numbers) is wrapped as IllegalArgumentException. Note the message in the throw is a plain string whereas a sibling Assert call uses %s formatting -- the two are differentiated by whether the regex matched.","triggerScenarios":"Passing a version string that passes the regex but fails Integer.parseInt (overflow values like '99999999999999.0'), or a value bypassing the Assert.hasText check.","commonSituations":"Parsing Docker API versions from unexpected daemon responses; user input with absurdly large version numbers; malformed environment-provided version strings.","solutions":["Validate the version string format and range before calling parse","Catch IllegalArgumentException and fall back to a known-good default version","Sanitize input to plausible Docker API version ranges (1.x to 2.x)"],"exampleFix":"// before\nApiVersion.parse(readFromUserInput)\n// after\nif (!readFromUserInput.matches(\"\\\\d+\\\\.\\\\d+\")) throw new IllegalArgumentException(\"bad version\");\nApiVersion.parse(readFromUserInput)","handlingStrategy":"validation","validationCode":"if (value == null || !value.matches(\"\\\\d+\\\\.\\\\d+\")) {\n    throw new IllegalArgumentException(\"Version must be \\\\d+.\\\\d+: \" + value);\n}\nApiVersion.parse(value);","typeGuard":null,"tryCatchPattern":"try { ApiVersion.parse(value); } catch (IllegalArgumentException ex) { log.warn(\"Unparseable Docker API version '{}', falling back to default\", value); return ApiVersion.of(1, 24); }","preventionTips":["Sanitize version strings to the expected major.minor shape before parsing","Catch IllegalArgumentException and provide a known-good default","Reject user-supplied versions outside plausible Docker API ranges"],"tags":["parsing","validation","buildpack"],"backgroundTag":null,"analyzedSha":"270dfe353fb830fd69b823a8a859287ff103854b","analyzedAt":"2026-08-11T19:42:06.541Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}