The message looks like Cargo has given up on your project: error: failed to select a version for the requirement. It has not. It is telling you something specific and checkable, that it searched the registry for a version of one crate matching the requirement you wrote and found none. The error is easy to read once you know which three lines carry the information, and nearly every occurrence falls into one of five causes. This post reproduces the most common, walks the diagnosis in the order that finds the answer fastest, and covers the case where two of your dependencies disagree. Output below is from Cargo 1.99.
Read the three useful lines
Take a manifest that asks for a major version that does not exist yet:
[package]
name = "t2"
version = "0.1.0"
edition = "2024"
[dependencies]
serde = "2"cargo check Updating crates.io index
error: failed to select a version for the requirement `serde = "^2"`
candidate versions found which didn't match: 1.0.229, 1.0.228, 1.0.227, ...
location searched: crates.io index
required by package `t2 v0.1.0 (/work/t2)`
help: if you are looking for the prerelease package it needs to be specified explicitly
serde = { version = "1.0.172-alpha.0" }The first line names the exact requirement after Cargo normalized it: "2" became ^2, meaning any version from 2.0.0 up to but not including 3.0.0. The second line is the clue that settles most cases: the candidate versions that exist, newest first. Here they are all 1.0.x, so the requirement is ahead of reality (or the author meant "1"). The third line says where Cargo looked, and the fourth says which package asked, which matters in a workspace or when the requirement comes from a dependency rather than your own manifest. The help text about prereleases is Cargo noting that a prerelease version of the crate exists but is never matched by a plain range.
Cause one: a typo or a requirement ahead of the registry
Compare the requirement with the candidate list. If the candidates are close to what you wanted, you typed the wrong number: tokio = "11" instead of "1", clap = "5" when the current major is 4. Fix it with cargo add serde, which writes the latest compatible requirement for you, or by looking up the current version on the registry. If the list says no matching package named instead, the name is wrong, and the error will say so differently: crates use hyphens and underscores interchangeably in use paths but the registry name is fixed, so serde_json and serde-json can be different crates. A misspelled name is also the opening move of a typosquatting attack, so double-check what you were given before adding it.
Cause two: two dependents want incompatible ranges
When the failing requirement does not appear in any manifest you wrote, a dependency generated it. Cargo resolves one version per semver-compatible range, but it can hold several majors at once; the failure happens only when ranges that must unify cannot, for example because a crate with a links key allows exactly one copy in the graph, or because two requirements on a 0.x crate leave no overlap inside a single major band. A typical message adds lines such as "required by package middle v0.3.0" and "... which satisfies dependency middle = "^0.3" of package app". Find the sources of the conflict with:
cargo tree -i openssl-sys
cargo tree -e features -i openssl-sysThe inverted tree lists every path that reaches the crate, so you can see which dependent holds a stale range. The options then are to upgrade the dependent whose range is too tight, to downgrade the other so that both agree, or, when upstream will not move, to carry a local fix with a patch. The two-versions case that does resolve, and the type-mismatch errors it causes, are described in multiple crate versions in the graph.
Cause three: a yanked or prerelease-only version
A version that the author yanked is excluded from fresh resolution but still works for lockfiles that already contain it. If the only versions satisfying your requirement are yanked, a new resolve fails, and the candidates list will look unexpectedly short or old. (Yanking explains the mechanism.) Prereleases behave differently again: 1.0.0-beta.2 never satisfies "1" or "^1.0". You must name the prerelease in the requirement, as in foo = "1.0.0-beta.2", and any dependency that carries a prerelease requirement forces its dependents to do the same. If a crate publishes only prereleases for months, that is the signal the library is not stable enough for a production lockfile.
Cause four: a requirement that the toolchain cannot meet
If the crate declares a rust-version newer than your compiler and your resolver honors it (the default for edition 2024 projects), Cargo skips those releases and may then find nothing that fits. The behavior depends on the resolver settings described in declaring the minimum Rust version. The message is different (it names the required rustc), but a project with an old toolchain often reports both. Upgrading Rust with rustup update is the fix when you are free to; otherwise pin the dependency to the last release that supports your compiler with cargo update name --precise VERSION.
Cause five: stale index or a registry you cannot reach
Cargo caches the registry index locally. After a crate publishes a release, a machine with an old cache will not see it until the index refreshes, which normally happens at the start of resolution. If you are offline or behind a mirror that lags, the candidates list is missing recent versions. Try cargo update with network access, or force a fresh fetch by deleting the cached index (rm -rf ~/.cargo/registry/index, safe as discussed in the Cargo home guide). With a private registry the cause is usually configuration: the dependency needs registry = "name" or Cargo searches crates.io for a crate that does not exist there, the situation described in private registries.
Fix the requirement, not the lockfile
A common wrong turn is deleting Cargo.lock hoping the problem goes away. The lockfile records the result of resolution; it never causes a failure to find a version, and removing it makes every dependency float to its latest release at once, which can add new failures. The right fix lives in the manifest or in the dependents that disagree. When it is fixed, run cargo update for the affected package and commit the lockfile change, per the lockfile policy. In workspaces, a requirement declared in one member can be the culprit for the whole build; workspaces and publishing shows how to keep versions in one place, and cargo tree is the tool for tracing every dependency edge.
When the message is a symptom of something else
If the version exists and your requirement is right, and Cargo still fails, suspect the environment: a corporate proxy rewriting the index responses, a clock far in the past breaking TLS, or a .cargo/config.toml in a parent directory replacing the crates.io source with an empty vendor directory. Run cargo -vv check to see which source Cargo reads and which config files it merged, and work from there instead of editing manifests blindly.



