Zum Inhalt springen

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.)

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`
email: String::from("[email protected]"),
active: true,
};
println!("{}", user.email);
}

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.

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.

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
email: String::from("[email protected]"),
active: true,
};
println!("{} ({}) aktiv: {}", user.name, user.email, user.active);
// Kurzschreibweise: die Variablennamen passen zu den Feldnamen
let name = String::from("Ada");
let email = String::from("[email protected]");
let other = User { name, email, active: false };
println!("{} ({}) aktiv: {}", other.name, other.email, other.active);
}

Ausgabe:

Ferris ([email protected]) aktiv: true
Ada ([email protected]) aktiv: false
▶ Selbst ausprobieren

Lö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"),
email: String::from("[email protected]"),
};
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:

localhost:8080 debug=true
▶ Selbst ausprobieren

Kommt 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).

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`
email: String::from("[email protected]"),
};
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 Cent
Beleg gesendet an [email protected]
▶ Selbst ausprobieren

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?.

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" }
▶ Selbst ausprobieren

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.

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.

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