Description
Problem
When using a private registry, I recently ran into a case where a crate version that is in the index (confirmed by cURLing the registry directly) could not be resolved by Cargo, giving me an error like
error: no matching package named `something` found
location searched: `private-registry` index
I quickly suspected that the index entry was invalid somehow, but Cargo gave no errors or warnings, even with CARGO_LOG=trace
. Furthermore, by tweaking http_remote.rs
, I found that its query to the registry (with an if-none-match
header) returned NotModified
, indicating Cargo did have the etag of the latest index file, which did include the crate/version in question. By removing the etag header, I also confirmed that the contents Cargo got from its request contained the version in question.
Long story short, I discovered that Cargo ends up swallowing errors related to invalid index entries. The first time Cargo downloads an index file with an invalid entry, it hits
cargo/src/cargo/core/summary.rs
Lines 345 to 348 in 05f54fd
However, that gets turned into a tracing::info
in
cargo/src/cargo/sources/registry/index/mod.rs
Lines 604 to 619 in 05f54fd
The user is likely to miss this since Cargo tracing logs are off by default, so they will just observe that Cargo claims the version doesn't exist.
Unfortunately, the issue doesn't stop there. If the user then tries to run with CARGO_LOG=trace
, they will then see no errors or warnings from Cargo. In fact, the logs will make it seem like the invalid entry doesn't exist at all. There will be no trace of it anywhere. This is because when Cargo parses an index entry, it caches the parsed lines so that it doesn't have to parse them again
cargo/src/cargo/sources/registry/index/mod.rs
Line 622 in 05f54fd
cargo/src/cargo/sources/registry/index/mod.rs
Lines 627 to 631 in 05f54fd
However, when a line can't be parsed, it doesn't cache that line (note the continue
where the error gets turned into tracing::info!
). It also doesn't leave that line as "unparsed" somewhere. So on subsequent invocations, Cargo grabs the version list from the cache manager to avoid parsing lines again, doesn't observe the (invalid) index entry for the version in question so it doesn't warn, then downloads the file again because it doesn't find the requested version, that download yields and empty response because the etag does match the latest index file, and so Cargo gives up.
So, two requests:
- Cargo should be louder when it finds an invalid index entry.
- Cargo should repeat the warning about an invalid index entry even if it's in an up-to-date cached version of the index file.
Steps
- Inject a new version with an invalid index entry into a registry.
- Take a dependency on said version.
- Run
cargo build
. - Observe that Cargo only says "version not found" with no further warnings.
- Re-run
cargo build
withCARGO_LOG=trace
. - Observe that there is no information in the logs about the invalid index entry which caused the version not to be found.
Possible Solution(s)
No response
Notes
In my case, the index entry parsing error I was eventually able to extract by disabling the if-none-match
logic and then running with CARGO_LOG=trace
was:
failed to parse "so/me/something" registry package: optional dependency `uom_0_35` is not included in any feature
Make sure that `dep:uom_0_35` is included in one of features in the [features] table.
I suspect, but am not quite sure, that this may be an erroneous index entry manipulation by the private registry provider we're using. Although it could also be that cargo publish
allowed publishing something with a nonsensical optional dependency in the first place?
Version
cargo 1.85.0 (05f54fdc3 2024-12-03)