Error E0560 de Rust: struct has no field named X (campo desconocido)
E0560 significa: estás creando un struct con Nombre { campo: valor }, y uno de los campos que escribiste no existe en ese struct. Normalmente es un error al escribir el nombre, un campo al que le cambiaron el nombre, o un campo que pertenece a otro struct. rustc suele decirte el nombre exacto que querías poner, así que es uno de los errores más rápidos de arreglar. (Esta página forma parte de Errores del compilador de Rust explicados.)
El mensaje de error
Sección titulada «El mensaje de error»error[E0560]: struct `User` has no field named `nmae` --> src/main.rs:9:9 |9 | nmae: String::from("Ferris"), // ❌ typo: the field is `name` | ^^^^ unknown field |help: a field with a similar name exists |9 - nmae: String::from("Ferris"), // ❌ typo: the field is `name`9 + name: String::from("Ferris"), // ❌ typo: the field is `name` |“Struct User has no field named nmae” quiere decir “el struct User no tiene ningún campo llamado nmae”. La etiqueta unknown field significa “campo desconocido”, y el help te avisa de que existe un campo con un nombre parecido.
Este es el programa que lo produce:
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { nmae: String::from("Ferris"), // ❌ typo: the field is `name` active: true, }; println!("{}", user.email);}Qué significa
Sección titulada «Qué significa»El titular nombra el struct (User) y el campo que escribiste (nmae). Los ^^^^ señalan ese campo dentro del bloque User { ... }. Rust lo comparó con la lista de campos de struct User y no encontró ninguno que coincidiera.
Debajo de la flecha te aparecerá una de estas tres pistas. Cada una te dice algo distinto:
help: a field with a similar name exists(existe un campo con un nombre parecido): un error al escribir. rustc te muestra la línea con el nombre correcto.note: available fields are: `username`(los campos disponibles son:username): no hay ningún nombre parecido. Estos son los campos que todavía no has rellenado.note: all struct fields are already assigned(ya se asignaron todos los campos del struct): rellenaste todos los campos reales, y este sobra.
Fíjate en que rustc no se queja además de que falta name. Corrige el nombre mal escrito y los dos problemas desaparecen a la vez.
Es como rellenar un formulario en papel y escribir tu número de teléfono en una casilla llamada “Fax”. El formulario no tiene esa casilla, así que el empleado te lo devuelve.
Por qué Rust hace esto
Sección titulada «Por qué Rust hace esto»Los campos de un struct quedan fijados cuando escribes struct User { ... }. Cada vez que creas un User, Rust comprueba que le diste exactamente esos campos: ni uno de menos, ni uno de más, ni uno mal escrito. Mira Definir y crear un struct.
Esto atrapa bugs reales. En JavaScript, { nmae: "Ferris" } crea sin avisar un objeto con la clave equivocada, y user.name acaba siendo undefined mucho más tarde, en otro sitio. En Rust, el error de escritura no pasa del compilador, así que cada User de tu programa tiene de verdad un name.
Cómo solucionarlo
Sección titulada «Cómo solucionarlo»Solución 1: Corrige el nombre
Sección titulada «Solución 1: Corrige el nombre»Elige esta cuando veas a field with a similar name exists. Usa el nombre de la línea help:. Los nombres de los campos distinguen entre mayúsculas y minúsculas, y Rust usa snake_case, así que userName y user_name son nombres distintos.
Ten cuidado también con la forma abreviada de inicialización de campos (field init shorthand): User { nmae, email } significa User { nmae: nmae, email: email }, así que el nombre de la variable tiene que coincidir con el del campo. Cambia el nombre de la variable o escribe el campo completo: User { name: nmae, email }.
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), // ✅ el nombre real del campo active: true, }; println!("{} ({}) activo: {}", user.name, user.email, user.active);
// forma abreviada: los nombres de las variables coinciden con los de los campos let name = String::from("Ada"); let other = User { name, email, active: false }; println!("{} ({}) activo: {}", other.name, other.email, other.active);}Salida:
Ferris ([email protected]) activo: trueAda ([email protected]) activo: falseSolución 2: Usa el nuevo nombre del campo, o añade el campo
Sección titulada «Solución 2: Usa el nuevo nombre del campo, o añade el campo»Elige esta cuando no hay ninguna pista de “similar name”. A menudo el struct cambió: alguien renombró name a username, o se eliminó un campo, pero este código sigue usando el antiguo. rustc te enumera los que quedan:
error[E0560]: struct `User` has no field named `name` --> src/main.rs:8:9 |8 | name: String::from("Ferris"), | ^^^^ `User` does not have this field | = note: available fields are: `username`La etiqueta dice que User no tiene este campo, y la note te enumera los campos disponibles.
Tienes dos opciones razonables. Si el struct está bien, usa el nombre actual del campo. Si tu código está bien y el struct de verdad necesita ese campo, añádelo a la definición del struct. Aquí Config dio all struct fields are already assigned para debug, y la solución es añadir debug al struct:
struct User { username: String, // antes se llamaba `name`: usa el nombre nuevo email: String,}
struct Config { port: u16, host: String, debug: bool, // añadido al struct, porque el código lo necesita}
fn main() { let user = User { username: String::from("ferris"), }; println!("{} ({})", user.username, user.email);
let config = Config { port: 8080, host: String::from("localhost"), debug: true, }; println!("{}:{} debug={}", config.host, config.port, config.debug);}Salida:
ferris ([email protected])localhost:8080 debug=trueSi el struct viene de un crate que acabas de actualizar, puede que el campo haya cambiado de nombre en la nueva versión. Busca el struct en docs.rs para esa versión, o mira el registro de cambios (changelog) del crate. Cuando añades un campo a tu propio struct, todos los sitios que lo crean también tienen que rellenarlo. rustc te señalará cada uno con E0063 (mira más abajo).
Solución 3: Usa el struct correcto
Sección titulada «Solución 3: Usa el struct correcto»Elige esta cuando el campo que escribiste sí existe, pero en otro struct. Con dos structs parecidos, como un Product con un title y un Customer con un name, es fácil confundirlos:
error[E0560]: struct `Product` has no field named `name` --> src/main.rs:13:9 |13 | name: String::from("Keyboard"), | ^^^^ `Product` does not have this field | = note: available fields are: `title`Mira la nota available fields. Si enumera campos que no esperabas, estás creando el struct equivocado. Usa el nombre del struct correcto, o el nombre del campo del struct que querías:
struct Product { title: String, price: u32, // en centavos}
struct Customer { name: String, email: String,}
fn main() { let keyboard = Product { title: String::from("teclado"), // los productos tienen un `title` price: 4900, }; let buyer = Customer { name: String::from("Ana"), // los clientes tienen un `name` }; println!("{} compra un {} por {} centavos", buyer.name, keyboard.title, keyboard.price); println!("Recibo enviado a {}", buyer.email);}Salida:
Ana compra un teclado por 4900 centavosRecibo enviado a [email protected]Solución 4: Usa paréntesis para un tuple struct
Sección titulada «Solución 4: Usa paréntesis para un tuple struct»Elige esta cuando el struct es un tuple struct, como struct Point(i32, i32);. Sus campos no tienen nombre, así que Point { x: 1, y: 2 } da E0560 tanto para x como para y, con help: `Point` is a tuple struct, use the appropriate syntax (Point es un tuple struct, usa la sintaxis adecuada) y la sugerencia Point(/* i32 */, /* i32 */). Créalo con paréntesis, Point(1, 2), y léelo con .0 y .1. Si prefieres tener nombres, cambia la definición a struct Point { x: i32, y: i32 }. Mira Cuándo usar una tupla y cuándo un struct.
Lo contrario: E0063, falta un campo
Sección titulada «Lo contrario: E0063, falta un campo»El gemelo de E0560 es E0063: un campo que el struct sí tiene, pero que no rellenaste. Rust nunca rellena campos por ti, así que cada campo necesita un valor:
error[E0063]: missing field `active` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `active`El mensaje quiere decir “falta el campo active al inicializar User”. Si faltan varios campos, los enumera todos: missing fields `active`, `email` and `login_count` in initializer of `User`. Solución: dale un valor a cada campo. Si muchos campos tienen valores por defecto razonables, deriva Default y usa la sintaxis de actualización de structs .. para rellenar el resto:
#[derive(Debug, Default)]struct Settings { volume: u8, dark_mode: bool, language: String,}
fn main() { // todos los campos escritos let full = Settings { volume: 80, dark_mode: false, language: String::from("es") };
// solo los campos que te interesan, el resto sale de Default let quick = Settings { dark_mode: true, ..Default::default() };
// copia el resto de otro valor let louder = Settings { volume: 100, ..full };
println!("{:?}", quick); println!("{:?}", louder);}Salida:
Settings { volume: 0, dark_mode: true, language: "" }Settings { volume: 100, dark_mode: false, language: "es" }El valor por defecto de un número es 0, el de un bool es false, y el de un String es una cadena vacía. Si quieres otros valores por defecto, escribe tú mismo impl Default for Settings. Mira Default: un valor inicial razonable.
Dónde lo verás normalmente
Sección titulada «Dónde lo verás normalmente»Dentro de la sintaxis de actualización ... Settings { dark: true, ..defaults } también da E0560. Aquí la nota enumera todos los campos (available fields are: `volume`, `dark_mode`, `language`), y puede que no haya pista de “similar name” cuando los nombres son demasiado distintos. Solución: dark_mode: true.
Variantes de enum con campos con nombre. Para enum Shape { Circle { radius: f64 } }, escribir Shape::Circle { r: 2.0 } es el mismo error, pero rustc usa otro código: E0559, variant `Shape::Circle` has no field named `r` (la variante Shape::Circle no tiene ningún campo llamado r), con la misma nota available fields y las mismas pistas para errores de escritura. Solución: Shape::Circle { radius: 2.0 }. Mira Los enums pueden guardar datos.
Un struct de otro módulo. Si el campo existe pero no es pub, obtienes en su lugar E0451, “field balance of struct Account is private” (el campo balance del struct Account es privado). Solución: usa el constructor del módulo, como Account::new(...). Mira Todo es privado por defecto.
Errores relacionados
Sección titulada «Errores relacionados»- E0609: no field
xon typeT: el mismo error de escritura, pero al leer un campo (user.nmae) en lugar de al crear el struct. - E0451: field is private in struct literal: el campo existe, pero no puedes asignarlo desde aquí.
- E0308: mismatched types: el nombre del campo está bien, pero el valor tiene el tipo equivocado, como
"Ferris"para un campoString. E0063: missing field in initializer: un campo que olvidaste (mira más arriba).E0559: variant has no field named x: el E0560 de las variantes de enum.- Todos los errores del compilador: la lista completa de páginas de errores.
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. rustc dice note: all struct fields are already assigned. ¿Qué significa?
2. Tienes let nmae = ...; y escribes User { nmae, email }. ¿Cómo lo arreglas?
3. ¿Qué error obtienes cuando dejas un campo sin poner, como User { name, email } sin active?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- E0560 — Rust error codes index (en inglés): la explicación oficial de este error.
- Defining and Instantiating Structs — El libro de Rust (en inglés): los literales de struct, la forma abreviada de inicialización de campos, la sintaxis de actualización y los tuple structs. También existe una traducción al español de la comunidad del libro.
- E0063 — Rust error codes index (en inglés): la página oficial del gemelo “missing field” (falta un campo) de este error.
- Struct expressions — The Rust Reference (en inglés): las reglas exactas de
Nombre { campo: valor }, la forma abreviada y..base. Default— documentación de la biblioteca estándar (en inglés): cómo funcionan#[derive(Default)]y..Default::default().