How to Use cargo outdated to Find Outdated Dependencies

Run `cargo outdated` to list dependencies with newer available versions, but first install the `cargo-outdated` subcommand since it is not included in the standard Rust toolchain.

When dependencies drift

You merge a pull request three weeks after the last release. The CI pipeline turns red. Your code is correct, but a dependency updated its API and your project silently pulled in a breaking change. Or maybe you're just curious: you added serde six months ago, and the ecosystem has moved on. You need to know what's stale without guessing.

Dependency drift is the gap between what your project uses and what the registry offers. Rust's lock file prevents drift by design. It freezes versions so your build is reproducible. That safety comes with a blind spot: you don't know what's new until you look. cargo outdated fills that gap. It reads your lock file, queries crates.io, and reports exactly which packages have newer versions available. It never modifies your project. It only tells you the truth.

How the tool fits into Cargo

Cargo ships with a core set of commands like build, test, and update. outdated is not one of them. It lives as a separate subcommand that you install into your user binaries. This keeps the core toolchain lean while letting the community maintain specialized tools.

Install the binary with cargo install. This compiles the tool from source and places the executable in ~/.cargo/bin, which Cargo adds to your PATH automatically.

# Install the subcommand globally.
# This compiles cargo-outdated and places it in ~/.cargo/bin.
cargo install cargo-outdated

The community convention is to run this once per machine. It's not part of the standard rustup toolchain, so it doesn't update when you run rustup update. If the tool itself gets a new release, you need to run cargo install cargo-outdated again to pick up the changes. The binary updates in place; you don't need to uninstall first.

Run the command from the root of your project. It looks for Cargo.toml and Cargo.lock in the current directory.

# Navigate to the project root.
# The tool reads Cargo.lock and compares against crates.io.
cargo outdated

The output is a table. Each row represents a dependency. The columns show the crate name, the version currently in your lock file, the latest version on crates.io, and a semantic versioning analysis. The tool scans every direct and transitive dependency. You see the full picture, not just the crates you listed in Cargo.toml.

Don't guess about versions. The lock file is your source of truth. cargo outdated is the window that shows you what lies beyond.

Reading the Semver column

The most important column is "Semver". Rust relies on semantic versioning to communicate compatibility. The tool analyzes the jump from your current version to the latest version and classifies the risk.

A "compatible" status means the major version is the same. The latest version is a minor or patch release. Upgrading is usually safe. The API surface hasn't changed in breaking ways. You can bump the version and expect your code to compile.

A "breaking" status means the major version changed. The crate author made changes that violate the public API contract. Functions might have moved, signatures might have changed, or behavior might have flipped. Upgrading requires you to edit Cargo.toml to accept the new major version, and you will likely need to fix compilation errors in your code.

The tool also shows "patch" updates. These are bug fixes within the same minor version. They are the safest upgrades. You get fixes without risk.

Some rows show a dash in the "Latest" column. This happens when the crate is not published on crates.io. Private registries, local paths, and git dependencies don't have a "latest" version in the public index. The tool can't compare them.

The Semver column is your risk meter. Green means safe. Breaking means work. Treat the report as a prioritized list of tasks.

Filtering the noise

Large projects have hundreds of dependencies. The default output can be overwhelming. You usually care about specific crates or specific types of updates. The tool provides flags to narrow the focus.

Check a single crate with --package. This is useful when you suspect a specific dependency is causing issues or when you want to audit a critical library.

# Check only the 'tokio' crate.
# This ignores unrelated packages to reduce noise.
cargo outdated --package tokio

The output still shows transitive dependencies of tokio. This helps you see the full chain. If tokio depends on mio, and mio is outdated, you see that too. You can't always update a transitive dependency directly. You might need to update the parent crate first. The filtered view makes these relationships visible.

Include pre-release versions with --include-pre. By default, the tool ignores alpha, beta, and nightly releases. Pre-releases are unstable. They might change or break. The flag lets you see them if you're testing new features or preparing for a major release.

# Include pre-release versions in the check.
# Useful when you want to test nightly features or beta releases.
cargo outdated --include-pre

Combine flags for precise queries. You can check a specific package and include pre-releases in one command. The tool parses the arguments and applies all filters before querying the registry.

Filter the noise. Focus on the breaking changes that matter to your project.

Realistic workflow: the pre-release audit

Teams use cargo outdated as part of their release process. Before cutting a new version, you want to ensure your dependencies are fresh. You also want to avoid pulling in breaking changes accidentally. The workflow looks like this.

First, refresh the lock file. cargo outdated compares against Cargo.lock. If your lock file is stale, the report is misleading. Run cargo update to bump all dependencies to the latest versions allowed by your Cargo.toml constraints. This moves your lock file to the current baseline.

# Update Cargo.lock to the latest compatible versions.
# This ensures cargo outdated compares against reality, not history.
cargo update

Next, run cargo outdated. Now the report shows only the gaps that require breaking changes or manual intervention. If the output is empty, your project is up to date within the bounds of your version requirements. If you see "breaking" entries, you have work to do.

Review the breaking changes. Check the changelogs of the affected crates. Decide if you want to upgrade. If you do, edit Cargo.toml to change the version requirement. For example, change serde = "1.0" to serde = "2.0". Then run cargo update again. The compiler will tell you what breaks. Fix the code. Test thoroughly.

This workflow separates safe updates from risky ones. cargo update handles the safe ones automatically. cargo outdated highlights the risky ones so you can make informed decisions.

Run cargo update before cargo outdated. Compare against reality, not history.

Pitfalls and edge cases

The tool is reliable, but it has limits. Understanding these limits prevents confusion.

The lock file is the input. If Cargo.lock is missing or corrupted, the tool fails. Run cargo build or cargo update to generate a fresh lock file. The tool cannot infer versions without the lock file.

Private registries require configuration. cargo outdated defaults to crates.io. If your project uses a private registry, the tool won't see those crates unless you configure it. You may need to pass --registry flags or set environment variables. Check the tool's documentation for registry support. Standard usage assumes the public index.

Transitive dependencies can be tricky. You might see a crate listed as outdated, but you can't update it directly. It's pulled in by another crate that pins an older version. The tool shows the dependency depth, which helps you trace the chain. You need to update the parent crate first. Sometimes you can't update at all until the parent crate releases a new version. This is normal. The dependency graph is a web, not a tree.

Git dependencies don't have versions in the same way. If you depend on a git repository, the tool shows the commit hash. It can't compare hashes to "latest" versions. You need to update the git reference manually.

Update the lock file first. Garbage in, garbage out.

Decision matrix

Choose the right tool for the job. Cargo provides several commands that interact with dependencies. Each has a specific role.

Use cargo outdated when you want a snapshot of version gaps without modifying files. This is the audit step. You read the report and decide what to do.

Use cargo update when you want to refresh Cargo.lock to the latest compatible versions. This is the safe upgrade step. It respects your Cargo.toml constraints and bumps versions within those bounds.

Use cargo update --package name when you want to bump a specific crate to the latest version allowed by your constraints. This is the targeted upgrade step. It updates one crate and its transitive dependencies, leaving the rest untouched.

Use manual Cargo.toml edits when you need to accept a breaking change by changing the version requirement. This is the risky upgrade step. You change the major version and then run cargo update to apply it.

Reach for cargo tree when you need to understand why a specific version is locked, not just what the latest version is. This command shows the full dependency graph with versions. It helps you debug conflicts and trace transitive dependencies.

Read before you write. cargo outdated tells you the risk. cargo update takes the leap.

Where to go next