[libmamba] Per-package repodata `url`/`urls` are discarded: `set_solvables_url` overwrites every solvable's URL with the channel-derived one
Summary
Packages whose files are not located at <channel>/<subdir>/<filename> (e.g. hosted as GitHub Release assets because the files exceed git's 100 MB limit, or on any off-channel storage advertised via the standard repodata urls field) cannot be installed by mamba/micromamba: libmamba always re-derives the download URL from the channel base URL and fails with 404, while classic conda honors urls and works with the same channel.
This is not merely a key-name gap; there are two independent problems:
Problem 1: only the singular url key is parsed
libmamba/src/specs/package_info.cpp,PackageInfo::from_json(tag 2.4.0; unchanged onmainas of 2026-09-01):pkg.package_url = j.value("url", "");No fallback to the standard
urlslist anywhere (grep for"urls"inlibmamba/src+libmamba/include: zero hits).
Problem 2 (the blocker): set_solvables_url unconditionally overwrites per-package URLs
Even when url is present in repodata and stored on the solvable by set_solvable (solv.set_url(pkg.package_url) in solver/libsolv/helpers.cpp), solver/libsolv/database.cpp calls, right after loading the repo:
set_solvables_url(p_repo, std::string(url), channel_id);and set_solvables_url (helpers.cpp) then rewrites the URL of every solvable to repo_url / file_name:
s.set_url((url / s.file_name()).str(specs::CondaURL::Credentials::Show));with the comment "The solvable url, this is not set in libsolv parsing so we set it manually". The per-package value set earlier is destroyed (per the adjacent comment it isn't even readable at that point). Consequently make_package_info materializes package_url = s.url() = <channel>/<subdir>/<filename>, Transaction considers it non-empty (so the url_for_channel_platform fallback never fires), and the fetcher 404s on the channel.
Reproduction
Channel
https://sunnyyangyangyang.github.io/ninfer-feedstock: repodata on GitHub Pages;.condafiles as GitHub Release assets. Entries carry bothurlsandurlkeys pointing at the release assets (verified byte-for-byte in the repodata file libmamba itself fetched and cached,~/.mamba/pkgs/cache/23f452bb.json).mamba install -p <prefix> ninfer(mamba 2.4.0, Fedora 44 RPM; same code on currentmain)libmamba downloads
<channel>/linux-64/<filename>.conda(does not exist) instead of the repodata-advertised URL:error libmamba Failed to download package from https://sunnyyangyangyang.github.io/ninfer-feedstock/linux-64/ninfer-...conda (status 404)The identical channel works with classic conda. Installing the same package by direct URL (
mamba install <release-asset-url>) works with mamba, confirming the channel-derived re-derivation is the failing step.
Suggested fix
In set_solvables_url, only set the channel-derived URL when the solvable has no per-package URL (i.e. make the overwrite conditional on the previously internalized package_url being empty), and in PackageInfo::from_json fall back to urls[0] when url is absent:
pkg.package_url = j.value("url", "");
if (pkg.package_url.empty()) {
if (auto u = j.find("urls"); u != j.end() && u->is_array() && !u->empty())
pkg.package_url = u->at(0).get<std::string>();
}Environment
- mamba 2.4.0 (Fedora 44 RPM
mamba-2.4.0-3.fc44.x86_64); micromamba affected (shared libmamba) - Verified against
mainbranch sources
Source: mamba-org/mamba