Quick answer
The first segment of a :: path can't be found. Check in order:
- External crate — is it actually in
Cargo.tomlunder[dependencies]? - Local module — did you declare it with
mod name;in its parent file? - Typo — crate and module names are case-sensitive.
- Behind a
#[cfg(...)]— the crate/feature is disabled in this build.
The exact error string
use serde::Serialize;
// error[E0433]: failed to resolve: use of undeclared crate or module `serde`
// --> src/main.rs:1:5
// |
// 1 | use serde::Serialize;
// | ^^^^^ use of undeclared crate or module `serde`
// a close relative you'll also see, for a type rather than a crate/module:
// error[E0433]: failed to resolve: use of undeclared type `Foo`
// and the sibling error code for the same underlying problem, reported
// specifically on a `use` statement:
// error[E0432]: unresolved import `serde::Serialize`
// |
// = help: no external crate `serde`
All three point at the same class of problem — a path segment the compiler can't locate — from slightly different code shapes. See the comparison table below for exactly which one you'll get where.
Cause 1: the crate isn't in Cargo.toml
By far the most common cause. Using an external crate requires it to be listed as a dependency — the 2018 edition removed the old extern crate foo; requirement, but the crate still has to be declared somewhere, and that somewhere is now Cargo.toml:
# Cargo.toml
[dependencies]
# serde = "1" ← ❌ missing entirely, or commented out
# Cargo.toml — ✅
[dependencies]
serde = { version = "1", features = ["derive"] }
After editing Cargo.toml, run cargo build — Cargo resolves and fetches the new dependency automatically; you don't run a separate "install" step the way npm or pip require.
Cause 2: a local module never declared with mod
Rust does not auto-discover module files from the filesystem. Creating src/utils.rs does nothing on its own — every module has to be declared explicitly with mod name; somewhere in its parent (usually main.rs or lib.rs for a top-level module):
// src/main.rs
// mod utils; ← ❌ missing — src/utils.rs exists but was never declared
fn main() {
utils::greet();
// error[E0433]: failed to resolve: use of undeclared crate or module `utils`
}
// src/main.rs
mod utils; // ✅ tells the compiler src/utils.rs (or src/utils/mod.rs) is part of the crate
fn main() {
utils::greet();
}
This is the case that surprises people most, because the file genuinely exists on disk and compiles on its own with no complaint — it's simply not part of the crate's module tree until something declares it with mod. The same rule applies one level deeper: a submodule inside utils/ needs its own mod declaration inside utils.rs (or utils/mod.rs).
Cause 3: wrong path form (2018+ edition rules)
Since the 2018 edition, paths inside a module are resolved relative to that module by default, which changes how you reference sibling items compared to the old 2015-edition rules:
// src/foo.rs
mod bar;
fn run() {
// bar::Thing ← ✅ this resolves fine, `bar` is a direct child module
// crate::foo::bar::Thing ← ✅ also fine, `crate::` is an explicit absolute path
}
If you're porting old 2015-edition code (which needed extern crate and different relative-path defaults) or copying a path from a different module's context, the segment that resolved there may not resolve here. When a relative path doesn't work, an absolute one starting with crate:: almost always does — it's unambiguous and worth reaching for first when debugging a stubborn E0433.
Cause 4: gated behind a disabled #[cfg(...)] or optional dependency
An optional crate dependency, or a module behind a feature flag, doesn't exist in a build where that feature isn't enabled — referencing it unconditionally fails only in the configurations without it:
# Cargo.toml
[dependencies]
tokio = { version = "1", optional = true }
[features]
async = ["tokio"]
use tokio::runtime::Runtime;
// error[E0433]: failed to resolve: use of undeclared crate or module `tokio`
// (only when built WITHOUT --features async)
The fix is either to build with the feature enabled (cargo build --features async), or — if the code should compile either way — gate the use and its call sites with the matching #[cfg(feature = "async")] so they're consistent with the dependency's own gate.
E0433 vs E0432 vs E0425
| Error | Where it fires | Typical fix |
|---|---|---|
| E0433 (this page) | A path used directly in code, e.g. foo::bar() | Add the crate to Cargo.toml, or declare the local mod |
| E0432 | Specifically on a use statement | Same fix — same underlying problem, different code shape |
| E0425 | A bare value, no :: at all | Fix scope/typo/order, or add self. |
Debugging checklist
- ✓ External crate? Confirm it's listed under
[dependencies]inCargo.toml, not just imagined - ✓ Local module? Confirm a
mod name;declaration exists in its parent file - ✓ Double-check spelling and case — crate names on crates.io are case-sensitive in
Cargo.toml - ✓ Try an absolute path starting with
crate::to rule out a relative-path mistake - ✓ Optional dependency? Check whether the required feature is enabled for this build
- ✓ Path has no
::at all? Wrong page — that's E0425 - ✓ Still stuck?
cargo treeconfirms whether the dependency actually resolved into your build at all
Frequently Asked Questions
What does 'failed to resolve: use of undeclared crate or module' mean?
Rust couldn't find the first segment of a :: path — usually a crate name at the start of a use statement or a fully-qualified path. The four real causes are: the crate isn't listed as a dependency in Cargo.toml, you're using a local module you never declared with mod, a typo in the crate or module name, or the item is behind a #[cfg(...)] that's disabled in this build.
How do I fix 'failed to resolve: use of undeclared crate or module'?
First check Cargo.toml — is the crate actually listed under [dependencies]? If it's a crate you wrote in a local file, confirm it's declared with mod name; in your crate root (main.rs or lib.rs) or an ancestor module — Rust doesn't auto-discover module files, every module needs an explicit mod statement somewhere in its parent.
What is the difference between E0433 and E0432?
They're the same underlying problem reported from two different places. E0432 fires specifically on an unresolved use statement — "unresolved import". E0433 fires when the same kind of unresolved path is used directly in code, like a fully-qualified call foo::bar() without a use at all. The fix is identical either way: add the crate to Cargo.toml, add the use, or declare the local mod.
How is E0433 different from E0425?
E0433 is for a path — an identifier followed by ::, such as foo::Bar — that fails to resolve because a crate, module, or import is missing. E0425 is for a bare value identifier with no :: after it, like an unresolved local variable. Check whether your unresolved name has a :: after it: if yes, you're looking at the right page (E0433); if no, see error[E0425]: cannot find value.
Do I still need extern crate in modern Rust?
No, not for ordinary dependencies. The 2018 edition removed the requirement to write extern crate foo; before using a crate — listing it in Cargo.toml and writing use foo::Bar; is enough. You'll still see extern crate in a handful of special cases, such as extern crate alloc; in #![no_std] crates or when explicitly renaming a crate at the extern-crate level, but for a normal Cargo.toml dependency it's unnecessary and considered legacy 2015-edition style.
More Rust & backend errors
Browse the full reference for Rust, Go, and Java errors — exact message, cause, and fix.