Skip to content

Nexus rejects newer system versions if the git commit is lexographically earlier #9071

@jgallagher

Description

@jgallagher

I tried to do a Nexus-driven update from 8571be3 (a commit on main) to 544f608 (the next commit on main), and the request to set the target system version was rejected with

Error Response: status: 400 Bad Request; headers: {"content-type": "application/json", "x-request-id": "68a82eaa-0b69-4da0-a9f0-e5eb67d2552a", "content-length": "240", "date": "Wed, 24 Sep 2025 14:55:29 GMT"}; value: Error { error_code: None, message: "The requested target system release (16.0.0-0.ci+git544f608e05a) is older than the current target system release (16.0.0-0.ci+git8571be38c0b). This is not supported.", request_id: "68a82eaa-0b69-4da0-a9f0-e5eb67d2552a" }

The source of this is where we do a comparison between two semver::Versions:

if version > system_version {
return Err(HttpError::for_bad_request(
None,
format!(
"The requested target system release ({system_version}) \
is older than the current target system release ({version}). \
This is not supported."
),
));
}

Because these versions match in their major/minor/patch, we're falling back to comparing the BuildMetadata, which is ordered lexicographically:

However for comparing build metadatas among one another, they do have a total order which is determined by lexicographic ordering of dot-separated components. Identifiers consisting of only digits are compared numerically. Otherwise, identifiers are compared in ASCII sort order. Any numeric identifier is always less than any non-numeric identifier.

We discussed a bunch of options for unblocking testing:

  • Relax this check to ignore the build metadata
  • Add a flag to the external API to override the version check in some way (e.g., "override: ignore build metadata")
  • Add an internal API to set the target release version, and give it an override flag

We're going to go with option 1; it's not any less safe than what we have today (where you can upgrade from commit to commit if the build metadata sometimes) and is very easy to implement.

At the update watercooler, we also discussed ways to make this more closely match requirements we'd actually like to enforce, such as upgrading from a commit on main to a newer commit on main (but not the other way around); upgrading from a release branch back to main (as long as the main commit is newer than the point of main where the release branch was forked); etc. A bunch of edge cases and subtleties came up in this discussion. @davepacheco plans to write an RFD to discuss this, but it's not an R17 ship blocker.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions