Rust Error E0609: No Field X on Type T
E0609 means: you wrote value.something, but the type of value has no field called something. Most of the time it’s a typo, or the value isn’t quite the type you think it is (an Option<User> instead of a User, for example). The error message tells you the exact type Rust sees, and that’s usually all you need to fix it. (This page is part of Rust compiler errors explained.)
The error message
Section titled “The error message”error[E0609]: no field `emial` on type `User` --> src/main.rs:12:25 |12 | println!("{}", user.emial); // ❌ typo: the field is `email` | ^^^^^ unknown field |help: a field with a similar name exists |12 - println!("{}", user.emial); // ❌ typo: the field is `email`12 + println!("{}", user.email); // ❌ typo: the field is `email` |This is the program that produces it:
struct User { name: String, email: String,}
fn main() { let user = User { name: String::from("Ferris"), }; println!("{}", user.name); println!("{}", user.emial); // ❌ typo: the field is `email`}What it means
Section titled “What it means”The headline has two parts, and both matter:
no field `emial`: the name after the dot that Rust couldn’t find.on type `User`: the type Rust thinksuserhas.
So first check the name, then check the type. If the type in the message is not the struct you expected, for example Option<User>, &Option<User>, Vec<User> or &T, the name is fine and the problem is that you need to get the struct out first.
It’s like asking a shop for “the blue one on the second shelf” when you’re standing in the wrong shop. The request is fine, you’re just in the wrong place.
Why Rust does this
Section titled “Why Rust does this”In Rust, every struct’s fields are fixed when you write the struct. The compiler knows the full list and checks every .field at compile time. There’s no “look it up at runtime and get undefined” like in JavaScript, or AttributeError like in Python: a wrong field name never makes it into your program. See Structs.
Wrapper types like Option<T> and Result<T, E> are separate types: your struct sits inside them, but they don’t have its fields. Rust doesn’t reach through them for you, because the value might not be there at all. You have to say what happens when it’s missing. See Option.
Generic code follows the same strict rule. In fn greet<T>(x: &T), T could be any type, including i32 or bool, which have no fields. Rust checks a generic function once for every possible T, so it only lets you use what your trait bounds promise. And traits can only promise methods, not fields. See Generics and Traits.
How to fix it
Section titled “How to fix it”Fix 1: Fix the spelling
Section titled “Fix 1: Fix the spelling”Choose this when the type in the message is the struct you expected. Look for the help: a field with a similar name exists line; rustc usually knows exactly which field you meant:
struct User { name: String, email: String,}
fn main() { let user = User { name: String::from("Ferris"), }; println!("{}", user.name); println!("{}", user.email); // ✅ the real field name}Output:
FerrisIf there’s no hint, jump to the struct definition (in most editors: Ctrl+click or F12 on the type) and copy the name from there. Field names are case-sensitive: userName and user_name are different fields.
Fix 2: Get the struct out of the Option first
Section titled “Fix 2: Get the struct out of the Option first”Choose this when the message says the type is Option<User>, Option<&User> or &Option<User>. This happens all the time with functions that might not find something, and with methods like .first(), .last(), .get() and .find():
error[E0609]: no field `name` on type `Option<User>` --> src/main.rs:11:25 |11 | println!("{}", user.name); | ^^^^ unknown field |help: one of the expressions' fields has a field of the same name |11 | println!("{}", user.unwrap().name); | +++++++++The .unwrap() hint compiles, but it crashes the program when the value is None. Better: decide what should happen in both cases, with if let, match, or map plus a default:
struct User { name: String,}
fn find_user(id: u32) -> Option<User> { if id == 1 { Some(User { name: String::from("Ferris") }) } else { None }}
fn main() { // if let: only run the code when there is a User if let Some(user) = find_user(1) { println!("Found: {}", user.name); }
// match: handle both cases match find_user(2) { Some(user) => println!("Found: {}", user.name), None => println!("No user with id 2"), }
// map + unwrap_or: take a field, or use a default let users = vec![User { name: String::from("Ada") }]; let first_name = users.first().map(|u| u.name.as_str()).unwrap_or("nobody"); println!("First user: {first_name}");}Output:
Found: FerrisNo user with id 2First user: AdaThe same patterns work on a reference to an Option. If maybe_user is a &Option<User>, write if let Some(user) = maybe_user and user is a &User. (For &Option<User> rustc gives no hint at all, so it’s worth remembering.) Inside a function that returns Option, let user = find_user(1)?; also works. See Handling an Option with match and if let.
Fix 3: Use .0 and .1 on tuple structs
Section titled “Fix 3: Use .0 and .1 on tuple structs”Choose this when the type is a tuple struct, like struct Point(i32, i32);. Its fields have no names, only positions, so p.x gives no field `x` on type `Point` (with the hint p.0). Use the position, or unpack it into named variables. If you want names, make it a struct with named fields:
struct Point(i32, i32); // tuple struct: fields are .0 and .1
struct Size { width: u32, // named fields: use .width and .height height: u32,}
fn main() { let p = Point(3, 4); println!("x = {}, y = {}", p.0, p.1);
let Point(x, y) = p; // or unpack it into named variables println!("squared distance = {}", x * x + y * y);
let screen = Size { width: 1920, height: 1080 }; println!("{}x{}", screen.width, screen.height);}Output:
x = 3, y = 4squared distance = 251920x1080Plain tuples work the same way. pair.2 on a two-element tuple gives E0609 with the note available fields are: `0`, `1`. See Accessing elements by position.
Fix 4: Use a trait method instead of a field on a generic T
Section titled “Fix 4: Use a trait method instead of a field on a generic T”Choose this when the message says on type `&T` (or T), with the label type parameter 'T' declared here. Code like this fails, even if every type you pass in has a name field:
fn greet<T>(animal: &T) { println!("Hello, {}!", animal.name); // ❌ no field `name` on type `&T`}Traits can’t require fields, but they can require a getter method. Define a small trait, implement it for each type, and add it as a bound on T:
trait Named { fn name(&self) -> &str;}
struct Dog { name: String,}
struct Robot { model: String,}
impl Named for Dog { fn name(&self) -> &str { &self.name }}
impl Named for Robot { fn name(&self) -> &str { &self.model // the field doesn't even need the same name }}
fn greet<T: Named>(thing: &T) { println!("Hello, {}!", thing.name()); // a method call, not a field}
fn main() { greet(&Dog { name: String::from("Rex") }); greet(&Robot { model: String::from("R2-D2") });}Output:
Hello, Rex!Hello, R2-D2!If the function only ever works with one type, you don’t need a generic at all: write fn greet(animal: &Dog) and animal.name works. See Traits as function parameters.
Where you’ll usually see it
Section titled “Where you’ll usually see it”A method without (). Writing word.len or cart.total (where total is a method) is close to E0609, but rustc gives a different code: E0615, “attempted to take value of method”, with the hint “use parentheses to call the method”. On a Vec, scores.len gives E0616, “field len of struct Vec is private”, because Vec really has a hidden field with that name. Same fix for both: word.len(), scores.len(), cart.total(). And "hello".length is plain E0609 on &str: in Rust it’s called len(). See Strings.
A Vec instead of one item. dogs.name on a Vec<Dog> gives no field `name` on type `Vec<Dog>`. A list has no name, each item does. Fix: pick one with dogs[0].name, or loop with for dog in &dogs { println!("{}", dog.name); }. See Vectors.
A Result instead of the value. load_config().port gives no field `port` on type `Result<Config, String>`, with the same .unwrap() hint. Fix: let config = load_config()?; inside a function that returns Result, or a match. See The ? operator.
A field on a number. age.value on a u32 is a different code again: E0610, “u32 is a primitive type and therefore doesn’t have fields”. Numbers, bool and char have no fields at all; you probably meant a struct variable.
Related errors
Section titled “Related errors”- E0599: no method named x found: the method version of this error. Often the same causes: a typo, or an
Optionthat needs unwrapping. - E0425: cannot find value in this scope: the variable before the dot doesn’t exist at all, or you forgot
self.in front of a field. - E0308: mismatched types: what you’ll often see next if you unwrap an
Optionin one place and not another. E0615: attempted to take value of method: you wrotex.leninstead ofx.len().E0616: field is private: the field exists but isn’tpub, likelenon aVec. Use the type’s methods.E0560: struct has no field named x: the same typo, but while creating the struct (User { emial: ... }).E0610: primitive type doesn't have fields:.somethingon a number,boolorchar.- All compiler errors explained
Quick check
Section titled “Quick check”Quick check
1. The error says there is no field name on type Option<User>. What does it tell you?
2. How do you read the first field of struct Meters(f64); from a value m?
3. In fn show<T>(x: &T), how can you read a name from every T?
Score: 0 / 3
Read more
Section titled “Read more”- E0609 — Rust error codes index: the official explanation of this error.
- Defining and Instantiating Structs — The Rust Book: named fields, dot access, and the struct update syntax.
- Tuple Structs — The Rust Book: structs whose fields are accessed by position, like
.0. - The Option Enum — The Rust Book: why
Option<T>andTare different types, and why you have to unwrap it. - Traits: Defining Shared Behavior — The Rust Book: trait methods and trait bounds, the right tool for generic code.