Rust-Fehler E0560: struct has no field named X (unbekanntes Feld)
E0560 bedeutet: Du erzeugst ein Struct mit Name { field: value }, und eines der Felder, die du geschrieben hast, gibt es in diesem Struct nicht. Meistens ist es ein Tippfehler, ein Feld, das umbenannt wurde, oder ein Feld, das zu einem anderen Struct gehört. rustc nennt dir oft genau den Namen, den du gemeint hast. Deshalb gehört dieser Fehler zu denen, die du am schnellsten behebst. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0560]: struct `User` has no field named `nmae` --> src/main.rs:9:9 |9 | nmae: String::from("Ferris"), // ❌ Tippfehler: das Feld heißt `name` | ^^^^ unknown field |help: a field with a similar name exists |9 - nmae: String::from("Ferris"), // ❌ Tippfehler: das Feld heißt `name`9 + name: String::from("Ferris"), // ❌ Tippfehler: das Feld heißt `name` |Auf Deutsch: „Das Struct User hat kein Feld namens nmae.“ Das help sagt: „Es gibt ein Feld mit einem ähnlichen Namen“, und zeigt die Zeile mit name.
Dieses Programm erzeugt den Fehler:
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { nmae: String::from("Ferris"), // ❌ Tippfehler: das Feld heißt `name` active: true, }; println!("{}", user.email);}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die Überschrift nennt das Struct (User) und das Feld, das du geschrieben hast (nmae). Die ^^^^ zeigen auf dieses Feld im Block User { ... }. Rust hat es mit der Feldliste in struct User verglichen und keinen Treffer gefunden.
Unter dem Pfeil bekommst du einen von drei Hinweisen. Jeder sagt dir etwas anderes:
help: a field with a similar name exists(es gibt ein Feld mit ähnlichem Namen): ein Tippfehler. rustc zeigt die Zeile mit dem richtigen Namen.note: available fields are: `username`(verfügbare Felder sind …): kein ähnlicher Name. Das sind die Felder, die du noch nicht ausgefüllt hast.note: all struct fields are already assigned(alle Felder sind schon zugewiesen): Du hast jedes echte Feld ausgefüllt, und dieses ist zu viel.
Beachte: rustc beschwert sich nicht zusätzlich, dass name fehlt. Behebst du den Tippfehler, verschwinden beide Probleme auf einmal.
Das ist, als würdest du auf einem Papierformular deine Telefonnummer in ein Kästchen namens „Fax“ schreiben. Das Formular hat so ein Kästchen nicht, also gibt der Sachbearbeiter es dir zurück.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Die Felder eines Structs stehen fest, sobald du struct User { ... } schreibst. Jedes Mal, wenn du einen User erzeugst, prüft Rust, dass du genau diese Felder angegeben hast: keins fehlt, keins zu viel, keins falsch geschrieben. Siehe Ein Struct definieren und erstellen.
Das fängt echte Bugs ab. In JavaScript erzeugt { nmae: "Ferris" } stillschweigend ein Objekt mit dem falschen Schlüssel, und user.name ist viel später irgendwo undefined. In Rust kommt der Tippfehler nicht am Compiler vorbei. Jeder User in deinem Programm hat also wirklich einen name.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: Die Schreibweise korrigieren
Abschnitt betitelt „Lösung 1: Die Schreibweise korrigieren“Nimm diese Lösung, wenn du a field with a similar name exists siehst. Nimm den Namen aus der help:-Zeile. Feldnamen unterscheiden Groß- und Kleinschreibung, und Rust benutzt snake_case. userName und user_name sind also verschiedene Namen.
Pass auch bei der Kurzschreibweise für Feldinitialisierung (Field Init Shorthand) auf: User { nmae, email } bedeutet User { nmae: nmae, email: email }. Der Variablenname muss also zum Feldnamen passen. Benenn entweder die Variable um, oder schreib das Feld aus: User { name: nmae, email }.
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), // ✅ der echte Feldname active: true, }; println!("{} ({}) aktiv: {}", user.name, user.email, user.active);
// Kurzschreibweise: die Variablennamen passen zu den Feldnamen let name = String::from("Ada"); let other = User { name, email, active: false }; println!("{} ({}) aktiv: {}", other.name, other.email, other.active);}Ausgabe:
Ferris ([email protected]) aktiv: trueAda ([email protected]) aktiv: falseLösung 2: Den neuen Feldnamen benutzen oder das Feld hinzufügen
Abschnitt betitelt „Lösung 2: Den neuen Feldnamen benutzen oder das Feld hinzufügen“Nimm diese Lösung, wenn es keinen Hinweis auf einen „ähnlichen Namen“ gibt. Oft hat sich das Struct geändert: Jemand hat name in username umbenannt, oder ein Feld wurde entfernt, aber dieser Code benutzt noch das alte. rustc zählt auf, was übrig ist:
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`Die Markierung sagt „User hat dieses Feld nicht“, und die note nennt die verfügbaren Felder.
Du hast zwei ehrliche Möglichkeiten. Ist das Struct richtig, benutze seinen aktuellen Feldnamen. Ist dein Code richtig und das Struct braucht das Feld wirklich, füge es zur Struct-Definition hinzu. Hier hat Config für debug die Meldung all struct fields are already assigned ergeben, und die Lösung ist, debug zum Struct hinzuzufügen:
struct User { username: String, // umbenannt von `name`: den neuen Namen benutzen email: String,}
struct Config { port: u16, host: String, debug: bool, // zum Struct hinzugefügt, weil der Code es braucht}
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);}Ausgabe:
ferris ([email protected])localhost:8080 debug=trueKommt das Struct aus einem Crate, das du gerade aktualisiert hast, wurde das Feld in der neuen Version vielleicht umbenannt. Sieh dir das Struct für diese Version auf docs.rs an, oder das Changelog des Crates. Fügst du deinem eigenen Struct ein Feld hinzu, muss jede Stelle, die es erzeugt, das Feld ebenfalls ausfüllen. rustc zeigt dir jede davon mit E0063 (siehe unten).
Lösung 3: Das richtige Struct benutzen
Abschnitt betitelt „Lösung 3: Das richtige Struct benutzen“Nimm diese Lösung, wenn es das Feld, das du geschrieben hast, zwar gibt – nur in einem anderen Struct. Bei zwei ähnlichen Structs, etwa einem Product mit title und einem Customer mit name, verwechselt man sie leicht:
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`Sieh dir die Notiz available fields an. Listet sie Felder auf, die du nicht erwartet hast, baust du das falsche Struct. Nimm den richtigen Struct-Namen oder den Feldnamen des Structs, das du gemeint hast:
struct Product { title: String, price: u32, // in Cent}
struct Customer { name: String, email: String,}
fn main() { let keyboard = Product { title: String::from("Tastatur"), // Produkte haben einen `title` price: 4900, }; let buyer = Customer { name: String::from("Ana"), // Kunden haben einen `name` }; println!("{} kauft eine {} für {} Cent", buyer.name, keyboard.title, keyboard.price); println!("Beleg gesendet an {}", buyer.email);}Ausgabe:
Ana kauft eine Tastatur für 4900 CentBeleg gesendet an [email protected]Lösung 4: Bei einem Tupel-Struct Klammern benutzen
Abschnitt betitelt „Lösung 4: Bei einem Tupel-Struct Klammern benutzen“Nimm diese Lösung, wenn das Struct ein Tupel-Struct ist, etwa struct Point(i32, i32);. Seine Felder haben keine Namen, also ergibt Point { x: 1, y: 2 } E0560 für x und für y, mit help: `Point` is a tuple struct, use the appropriate syntax (Point ist ein Tupel-Struct, benutze die passende Syntax) und dem Vorschlag Point(/* i32 */, /* i32 */). Erzeuge es mit Klammern, Point(1, 2), und lies es mit .0 und .1. Hättest du lieber Namen, ändere die Definition zu struct Point { x: i32, y: i32 }. Siehe Tupel oder Struct?.
Das Gegenstück: E0063 missing field
Abschnitt betitelt „Das Gegenstück: E0063 missing field“Der Zwilling von E0560 ist E0063: ein Feld, das das Struct hat, das du aber nicht ausgefüllt hast. Rust füllt nie Felder für dich aus, also braucht jedes Feld einen Wert:
error[E0063]: missing field `active` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `active`Auf Deutsch: „Feld active fehlt beim Erzeugen von User.“ Fehlen mehrere Felder, nennt die Meldung alle: missing fields `active`, `email` and `login_count` in initializer of `User`. Lösung: Gib jedem Feld einen Wert. Haben viele Felder sinnvolle Standardwerte, leite Default ab und füll den Rest mit der Update-Syntax für Structs .. auf:
#[derive(Debug, Default)]struct Settings { volume: u8, dark_mode: bool, language: String,}
fn main() { // jedes Feld ausgeschrieben let full = Settings { volume: 80, dark_mode: false, language: String::from("en") };
// nur die Felder, die dich interessieren, der Rest aus Default let quick = Settings { dark_mode: true, ..Default::default() };
// den Rest von einem anderen Wert übernehmen let louder = Settings { volume: 100, ..full };
println!("{:?}", quick); println!("{:?}", louder);}Ausgabe:
Settings { volume: 0, dark_mode: true, language: "" }Settings { volume: 100, dark_mode: false, language: "en" }Der Standardwert einer Zahl ist 0, für bool ist es false, und ein String ist leer. Willst du andere Standardwerte, schreib impl Default for Settings selbst. Siehe Default: ein sinnvoller Startwert.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“In der Update-Syntax mit ... Auch Settings { dark: true, ..defaults } ergibt E0560. Hier listet die Notiz alle Felder auf (available fields are: `volume`, `dark_mode`, `language`), und es gibt vielleicht keinen Hinweis auf einen „ähnlichen Namen“, wenn die Namen zu verschieden sind. Lösung: dark_mode: true.
Enum-Varianten mit benannten Feldern. Bei enum Shape { Circle { radius: f64 } } ist Shape::Circle { r: 2.0 } derselbe Fehler, aber rustc benutzt einen anderen Code: E0559, variant `Shape::Circle` has no field named `r` (die Variante hat kein Feld namens r), mit derselben Notiz available fields und denselben Hinweisen bei Tippfehlern. Lösung: Shape::Circle { radius: 2.0 }. Siehe Enums können Daten enthalten.
Ein Struct aus einem anderen Modul. Gibt es das Feld, aber es ist nicht pub, bekommst du stattdessen E0451, „field balance of struct Account is private“ (das Feld ist privat). Lösung: Benutze den Konstruktor des Moduls, etwa Account::new(...). Siehe Alles ist standardmäßig privat.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0609: no field
xon typeT: derselbe Tippfehler, aber beim Lesen eines Felds (user.nmae) statt beim Erzeugen des Structs. - E0451: field is private in struct literal: Das Feld gibt es, aber du darfst es von hier aus nicht setzen.
- E0308: mismatched types: Der Feldname stimmt, aber der Wert hat den falschen Typ, etwa
"Ferris"für einString-Feld. E0063: missing field in initializer: ein Feld, das du vergessen hast (siehe oben).E0559: variant has no field named x: E0560 für Enum-Varianten.- Alle Compilerfehler einfach erklärt
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. rustc sagt note: all struct fields are already assigned. Was bedeutet das?
2. Du hast let nmae = ...; und schreibst User { nmae, email }. Wie behebst du das?
3. Welchen Fehler bekommst du, wenn du ein Feld weglässt, etwa User { name, email } ohne active?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0560 – Rust error codes index (auf Englisch): die offizielle Erklärung dieses Fehlers.
- Strukturen definieren und instanziieren – Das Rust-Buch: Struct-Literale, die Kurzschreibweise für Felder, die Update-Syntax und Tupel-Structs.
- E0063 – Rust error codes index (auf Englisch): die offizielle Seite zum Zwilling „missing field“ dieses Fehlers.
- Struct expressions – The Rust Reference (auf Englisch): die genauen Regeln für
Name { field: value }, die Kurzschreibweise und..base. Default– Doku der Standardbibliothek (auf Englisch): wie#[derive(Default)]und..Default::default()funktionieren.