Rust: error[E0433]: failed to resolve: use of undeclared crate or module

Quick answer

The first segment of a :: path can't be found. Check in order:

  • External crate — is it actually in Cargo.toml under [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

ErrorWhere it firesTypical 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
E0432Specifically on a use statementSame fix — same underlying problem, different code shape
E0425A bare value, no :: at allFix scope/typo/order, or add self.

Debugging checklist

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.

All Error References Rust E0425: cannot find value Rust E0277: trait bound not satisfied
About the author

Pasindu Ishan is a software developer based in Sri Lanka. He builds privacy-first developer tools at JSON Dev Tools.