Ir al contenido

Error E0432 de Rust: unresolved import (importación no resuelta)

E0432 significa que una de tus líneas use apunta a algo que Rust no encuentra. Quizá el crate todavía no está en Cargo.toml, quizá hay una pequeña errata en la ruta, o quizá el archivo existe pero Rust no sabe que es un módulo. Asusta un poco, pero casi siempre se arregla con una sola línea, y normalmente el compilador te dice cuál. Esta página forma parte de la guía de errores del compilador.

error[E0432]: unresolved import `rand`
--> src/main.rs:1:5
|
1 | use rand::random_range;
| ^^^^ use of unresolved module or unlinked crate `rand`
|
= help: if you wanted to use a crate named `rand`, use `cargo add rand` to add it to your `Cargo.toml`

Este es el programa que lo produce, en un proyecto recién creado con cargo new y sin nada bajo [dependencies]:

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("Sacaste un {roll}");
}

El texto bajo los ^^^^ cambia según la causa. Todos estos casos son E0432, y cada uno te lleva a una solución distinta de las de abajo:

Lo que dice la etiqueta Lo que suele haber fallado Solución
use of unresolved module or unlinked crate falta el crate en Cargo.toml, o un archivo no tiene su línea mod Solución 1 o 3
could not find `collection` in `std` una errata en medio de la ruta Solución 2
no `Hashmap` in `collections` una errata (o mayúsculas mal puestas) en el último nombre Solución 2
could not find `inventory` in the crate root una ruta crate:: hacia un módulo que no está declarado Solución 3
no external crate la ruta empieza en el módulo equivocado Solución 4

Una línea use es un atajo. use rand::random_range; dice “a partir de ahora, random_range significa lo que hay en rand::random_range”. Antes de crear ese atajo, Rust tiene que recorrer la ruta pieza a pieza: primero encontrar rand y después encontrar random_range dentro.

Los ^^^^ señalan la primera pieza que falló. Aquí es rand, el primer segmento, así que Rust ni siquiera llegó a buscar random_range. La línea help: adivina el motivo: rand es un crate de crates.io, y este proyecto no lo ha añadido. “Unresolved import” significa justo eso: una importación que Rust no pudo resolver.

Es como darle a un taxista la dirección “Calle del Puerto 12, Springfeld”. Si el nombre del pueblo está mal, el taxista no puede ni empezar a buscar la calle.

Rust resuelve todas las rutas al compilar, no cuando el programa se ejecuta. No se carga nada “por si acaso”. Tu código solo puede ver tres tipos de cosas: los crates que aparecen en Cargo.toml (además de std), los módulos que declaraste con mod y los elementos que hay dentro de ellos. Si una línea use nombra algo fuera de ese conjunto, Rust se detiene en el acto en lugar de adivinar.

Y eso es bueno. Una importación mal escrita en Python o JavaScript a menudo solo falla cuando esa línea por fin se ejecuta, quizá en producción. En Rust el programa ni siquiera compila. Además, así un crate que nunca añadiste no puede colarse en tu programa.

Desde la edición 2018, una ruta de use empieza en uno de estos sitios: el nombre de un crate (std, rand), crate (la raíz de tu propio crate), self (el módulo actual), super (el módulo padre) o un módulo declarado en el módulo actual. La lección de Módulos lo explica en detalle, y Cargo y crates explica las dependencias.

Elige esta cuando el primer segmento es un crate de crates.io, como rand, serde o regex, y la línea help: menciona cargo add. Es la causa más común, sobre todo cuando copias código de un blog. Ejecuta esto en la carpeta que contiene Cargo.toml:

Terminal window
cargo add rand

Cargo busca la versión más reciente y añade una línea a Cargo.toml por ti:

[dependencies]
rand = "0.10.3"

Ahora el mismo código compila. Esta versión imprime una comprobación en lugar de la tirada en sí, para que la salida sea siempre la misma:

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("La tirada está entre 1 y 6: {}", (1..=6).contains(&roll));
}

Salida:

La tirada está entre 1 y 6: true
▶ Pruébalo tú mismo

Aquí hay dos cosas que suelen confundir. Primero, los nombres de crate con guion se escriben con guion bajo en el código: haces cargo add tracing-subscriber, pero escribes use tracing_subscriber::.... Segundo, si el crate es una dependencia de tu workspace, igualmente tiene que aparecer en el Cargo.toml del paquete que lo usa.

Solución 2: Corrige cómo está escrita la ruta

Sección titulada «Solución 2: Corrige cómo está escrita la ruta»

Elige esta cuando la etiqueta dice could not find `X` in `Y` (no se encuentra X en Y) o no `X` in `Y` (no hay X en Y). Algo en medio o al final de la ruta está mal escrito. Un clásico:

error[E0432]: unresolved import `std::collection`
--> src/main.rs:1:10
|
1 | use std::collection::HashMap;
| ^^^^^^^^^^ could not find `collection` in `std`

El módulo se llama collections, con s. Los nombres también distinguen mayúsculas y minúsculas: use std::collections::Hashmap; falla con no `Hashmap` in `collections`, y rustc añade help: a similar name exists in the module (existe un nombre parecido en el módulo) con la forma correcta. La importación corregida:

use std::collections::HashMap;
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("manzanas", 12);
println!("{:?}", stock.get("manzanas"));
}

Salida:

Some(12)
▶ Pruébalo tú mismo

Si no estás seguro de la ruta exacta, búscala en la documentación de la biblioteca estándar (en inglés). La página de cada elemento muestra su ruta completa arriba del todo. En HashMaps tienes más sobre este tipo.

Elige esta cuando creaste un archivo nuevo, por ejemplo src/inventory.rs, y use inventory::... no lo encuentra. En Rust, un archivo no es un módulo hasta que un archivo padre lo declara. Tu proyecto se ve así:

src/
├── main.rs use inventory::count_items; ← falta `mod inventory;`
└── inventory.rs pub fn count_items() -> u32 { 42 }

Y rustc te dice exactamente qué falta:

error[E0432]: unresolved import `inventory`
--> src/main.rs:1:5
|
1 | use inventory::count_items;
| ^^^^^^^^^ use of unresolved module or unlinked crate `inventory`
|
help: to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module
|
1 + mod inventory;
|

La ayuda dice: “para usar el archivo src/inventory.rs, declara el módulo con mod inventory en este archivo”. Añade mod inventory; al principio de src/main.rs (o de src/lib.rs, si el módulo pertenece a tu biblioteca). Escribir use crate::inventory::count_items; en su lugar no ayuda: falla con could not find `inventory` in the crate root (no se encuentra inventory en la raíz del crate), porque el módulo sigue sin estar declarado.

En el Playground todo vive en un solo archivo, así que aquí el módulo se escribe en línea con mod inventory { ... }. Funciona exactamente igual que el archivo separado:

mod inventory {
pub fn count_items() -> u32 {
42
}
}
use inventory::count_items;
fn main() {
println!("Artículos en inventario: {}", count_items());
}

Salida:

Artículos en inventario: 42
▶ Pruébalo tú mismo

Declara cada módulo una sola vez, en su padre. Los demás archivos llegan a él con use crate::inventory::.... No añadas mod inventory; en cada archivo que lo use.

Solución 4: Empieza la ruta desde el sitio correcto

Sección titulada «Solución 4: Empieza la ruta desde el sitio correcto»

Elige esta cuando la importación está dentro de un módulo y el elemento vive en otro módulo de tu propio crate. Aquí receipt está dentro de shop y quiere shop::store_name:

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod receipt {
use store_name; // ❌ busca en el sitio equivocado
pub fn header() -> String {
format!("== {} ==", store_name())
}
}
}
error[E0432]: unresolved import `store_name`
--> src/main.rs:7:13
|
7 | use store_name; // ❌ busca en el sitio equivocado
| ^^^^^^^^^^ no external crate `store_name`

Un nombre suelto al principio de una ruta use significa “un crate, o algo declarado aquí mismo, en este módulo”. store_name no es ninguna de las dos cosas, así que Rust buscó un crate con ese nombre y no lo encontró (“no external crate”, no hay ningún crate externo). Dile por dónde empezar:

Prefijo Empieza desde Ejemplo
crate:: la raíz de tu crate (main.rs o lib.rs) use crate::shop::prices::price_of;
super:: el módulo padre use super::store_name;
self:: el módulo actual use self::lines::line;

Los tres en un mismo programa:

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod prices {
pub fn price_of(item: &str) -> u32 {
if item == "manzana" { 3 } else { 5 }
}
}
pub mod receipt {
use super::store_name; // módulo padre: shop
use crate::shop::prices::price_of; // desde la raíz del crate
use self::layout::line; // hijo de este módulo
mod layout {
pub fn line(item: &str, price: u32) -> String {
format!("{item}: {price}")
}
}
pub fn print(item: &str) {
println!("== {} ==", store_name());
println!("{}", line(item, price_of(item)));
}
}
}
fn main() {
shop::receipt::print("manzana");
}

Salida:

== Ferris Fruits ==
manzana: 3
▶ Pruébalo tú mismo

use layout::line; también funcionaría aquí, porque layout está declarado en el módulo actual; self:: solo lo hace explícito. Si tienes dudas, crate:: con la ruta completa funciona desde cualquier parte de tu crate, y rustc a menudo lo sugiere: help: a similar path exists (existe una ruta parecida) seguido de la versión con crate::.

Código escrito para una versión antigua de un crate. Muchos tutoriales usan rand 0.8. Con rand 0.10 obtienes:

error[E0432]: unresolved import `rand::thread_rng`
--> src/main.rs:1:5
|
1 | use rand::thread_rng;
| ^^^^^^^^^^^^^^^^ no `thread_rng` in the root

rustc encontró el crate rand, pero en su raíz ya no hay nada llamado thread_rng. Solución: consulta la documentación del crate en docs.rs para la versión que tienes en Cargo.toml. Aquí el nombre nuevo es rand::rng(). Mira Números aleatorios.

Un paquete con main.rs y lib.rs a la vez. Son dos crates distintos. Dentro de main.rs, crate:: significa el binario, así que use crate::inventory::count_items; falla con could not find `inventory` in the crate root aunque lib.rs tenga pub mod inventory;. Solución: usa el nombre del paquete, use shop_app::inventory::count_items; (con los guiones convertidos en guiones bajos).

El elemento existe, pero es privado. Ese es otro error, E0603, no E0432:

error[E0603]: function `count_items` is private
--> src/main.rs:7:16
|
7 | use inventory::count_items;
| ^^^^^^^^^^^ private function

Aquí Rust sí encontró count_items, pero la función es privada (“private function”). Solución: añade pub delante del fn (y delante de cada mod del camino, porque un módulo privado da module `prices` is private). Mira Módulos.

  • E0433: una ruta dentro de tu código (como HashMap::new() o rand::rng()) no se puede resolver. Las mismas causas, pero no en una línea use.
  • E0425: no se encuentra un valor o una función; a menudo lo arregla la misma línea use.
  • E0603: la importación se encontró, pero es privada. Añade pub.
  • E0463: can't find crate (no se encuentra el crate), que aparece con extern crate rand; cuando el crate no está en Cargo.toml.
  • Todos los errores del compilador: la lista completa de páginas de errores.

Comprueba lo aprendido

1. Copiaste use serde::Serialize; en un proyecto nuevo y obtienes un E0432 que dice que el crate serde no está resuelto o enlazado. ¿Cuál es la solución?

2. Creaste src/billing.rs, pero use billing::total; en main.rs falla. ¿Qué falta?

3. Dentro de mod shop { mod receipt { ... } }, ¿cómo importa receipt una función definida directamente en shop?

Puntuación: 0 / 3