{"record":{"id":"d24e44b3917feabd","repo":"apache/beam","slug":"expected-the-version-string-to-start-with-major-minor-but","errorCode":null,"errorMessage":"Expected the version string to start with `<major>.<minor>` but received ","messagePattern":"Expected the version string to start with `<major>\\.<minor>` but received ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/TransformUpgrader.java","lineNumber":490,"sourceCode":"      return in.readObject();\n    } catch (InvalidClassException e) {\n      LOG.info(\n          \"An object cannot be re-generated from the provided byte array. Caller may use the \"\n              + \"default value for the parameter when upgrading. Underlying error: {}\",\n          e.toString());\n      throw e;\n    } catch (Exception e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  @SuppressWarnings({\n    \"nullness\" // TODO(https://github.com/apache/beam/issues/20497)\n  })\n  private static Version getVersionFromStr(String version) {\n    String[] versionParts = Splitter.onPattern(\"\\\\.\").splitToList(version).toArray(new String[0]);\n    if (versionParts.length < 2) {\n      throw new IllegalArgumentException(\n          \"Expected the version string to start with `<major>.<minor>` \"\n              + \"but received \"\n              + version);\n    }\n\n    // Concatenating patch and suffix to determine the correct patch version.\n    String patchAndSuffix =\n        versionParts.length == 2\n            ? \"\"\n            : String.join(\".\", Arrays.copyOfRange(versionParts, 2, versionParts.length));\n    StringBuilder patchVersionBuilder = new StringBuilder();\n    for (int i = 0; i < patchAndSuffix.length(); i++) {\n      if (Character.isDigit(patchAndSuffix.charAt(i))) {\n        patchVersionBuilder.append(patchAndSuffix.charAt(i));\n      } else {\n        break;\n      }\n    }","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/TransformUpgrader.java#L472-L508","documentation":"compareVersions parses version strings via getVersionFromStr, which requires at least a `<major>.<minor>` form. A string with fewer than two dot-separated parts (e.g. \"7\" or \"\") cannot be compared and causes an IllegalArgumentException.","triggerScenarios":"Calling compareVersions (e.g. for transform service version checks via TransformUpgrader) with a version string like \"8\" or \"\" instead of \"8.1.0\".","commonSituations":"Environment variables or service responses reporting only a major version; typos in configured versions; build metadata stripped of minor/patch parts.","solutions":["Pass a full version string with at least major.minor, e.g. \"2.54.0\"","Normalize the version string before comparison (append missing \".0\" parts)","Guard the input with a regex check like ^\\d+\\.\\d+ before calling compareVersions"],"exampleFix":"// before\nTransformUpgrader.compareVersions(\"8\", \"2.54.0\") >= 0;\n// after\nTransformUpgrader.compareVersions(\"8.0.0\", \"2.54.0\") >= 0;","handlingStrategy":"validation","validationCode":"import java.util.regex.Pattern;\nprivate static final Pattern VERSION = Pattern.compile(\"^\\\\d+\\\\.\\\\d+\");\nif (version == null || !VERSION.matcher(version).find()) {\n  throw new IllegalArgumentException(\"Version must be <major>.<minor>[.<patch>]: \" + version);\n}","typeGuard":null,"tryCatchPattern":"try {\n  TransformUpgrader.compareVersions(a, b);\n} catch (IllegalArgumentException e) {\n  // fallback: pad version e.g. a + \".0.0\" and retry\n}","preventionTips":["Always pass full semver strings (major.minor.patch)","Normalize versions read from env vars or service metadata before comparison"],"tags":["java","beam","version-parsing","invalid-input"],"backgroundTag":"invalid-version-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}