Vibe Engines
YouTube
  • Reference
  • 27 errors

Rust compiler errors, explained

Each entry is the smallest program that triggers one code, the real output, and the fix that compiles. Re-checked on every build.

27 of 27 errors

Ownership and moves 5

A value has one owner. These fire when you gave it away, or never had it.

E0382Use of a moved value

You handed a value to someone else — another variable, a function call — and then tried to use it again. In Python both names would point at the same object. In Rust the value has exactly one owner, and giving it away ends your claim to it.

fn main() {
let prompt = String::from("Summarise this contract");
let sent = prompt;
println!("{prompt} {sent}");
}
error[E0382]: borrow of moved value: `prompt`
 --> src/main.rs:4:16
  |
2 |     let prompt = String::from("Summarise this contract");
  |         ------ move occurs because `prompt` has type `String`, which does not implement the `Copy` trait
3 |     let sent = prompt;
  |                ------ value moved here
4 |     println!("{prompt} {sent}");
  |                ^^^^^^ value borrowed here after move
  |
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let sent = prompt.clone();
  |                      ++++++++

The usual fix. Borrow instead of move (&prompt), clone if you really need two copies, or restructure so the second use comes first.

fn main() {
let prompt = String::from("Summarise this contract");
let sent = &prompt;
println!("{prompt} {sent}");
}

Taught in: 4.2 Handing over the key

Link to E0382

E0384Assigned twice to an immutable variable

Variables are immutable unless you say otherwise. Rust makes the decision to change a value visible at the declaration, so a reader never has to scan a function to learn what can move.

fn main() {
let tokens_left = 4096;
tokens_left = 4000;
println!("{tokens_left}");
}
error[E0384]: cannot assign twice to immutable variable `tokens_left`
 --> src/main.rs:3:5
  |
2 |     let tokens_left = 4096;
  |         ----------- first assignment to `tokens_left`
3 |     tokens_left = 4000;
  |     ^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut tokens_left = 4096;
  |         +++

The usual fix. Add mut to the declaration, or — often better — shadow the name with a new let.

fn main() {
let mut tokens_left = 4096;
tokens_left = 4000;
println!("{tokens_left}");
}

Taught in: 2.2 Values that change

Link to E0384

E0505Moved out while it was still borrowed

A reference to the value is still going to be used later, and you moved the value away. The reference would point at something that no longer belongs to you.

fn main() {
let prompt = String::from("p");
let r = &prompt;
let moved = prompt;
println!("{r} {moved}");
}
error[E0505]: cannot move out of `prompt` because it is borrowed
 --> src/main.rs:4:17
  |
2 |     let prompt = String::from("p");
  |         ------ binding `prompt` declared here
3 |     let r = &prompt;
  |             ------- borrow of `prompt` occurs here
4 |     let moved = prompt;
  |                 ^^^^^^ move out of `prompt` occurs here
5 |     println!("{r} {moved}");
  |                - borrow later used here
  |
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let r = &prompt.clone();
  |                    ++++++++

The usual fix. Use the reference before the move, or borrow instead of moving.

fn main() {
let prompt = String::from("p");
let r = &prompt;
println!("{r}");
let moved = prompt;
println!("{moved}");
}

Link to E0505

E0507Cannot move out of a borrow

You have a reference to a struct and tried to take one of its owned fields out. The struct still belongs to its owner; you cannot walk off with a piece of it.

struct Doc {
text: String,
}
 
fn take(d: &Doc) -> String {
d.text
}
 
fn main() {
let d = Doc { text: String::from("x") };
println!("{}", take(&d));
}
error[E0507]: cannot move out of `d.text` which is behind a shared reference
 --> src/main.rs:6:5
  |
6 |     d.text
  |     ^^^^^^ move occurs because `d.text` has type `String`, which does not implement the `Copy` trait
  |
help: consider cloning the value if the performance cost is acceptable
  |
6 |     d.text.clone()
  |           ++++++++

The usual fix. Return a reference (&d.text), clone the field, or take the whole struct by value.

struct Doc {
text: String,
}
 
fn take(d: &Doc) -> String {
d.text.clone()
}
 
fn main() {
let d = Doc { text: String::from("x") };
println!("{}", take(&d));
}

Link to E0507

E0381Used a possibly-uninitialised variable

Rust has no “default zero” — a variable must be given a value on every path before it is read.

fn main() {
let n: i32;
println!("{n}");
}
error[E0381]: used binding `n` isn't initialized
 --> src/main.rs:3:16
  |
2 |     let n: i32;
  |         - binding declared here but left uninitialized
3 |     println!("{n}");
  |                ^ `n` used here but it isn't initialized
  |
help: consider assigning a value
  |
2 |     let n: i32 = 42;
  |                ++++

The usual fix. Initialise it where it is declared, or make sure every branch assigns it.

fn main() {
let n: i32 = 0;
println!("{n}");
}

Link to E0381

Borrowing and mutability 4

Many readers or one writer, never both, and only if you said mut.

E0502Mutable borrow while an immutable borrow is alive

Someone is still reading through a reference while you try to change the thing they are reading. In Python this is the “list changed size during iteration” bug — Rust refuses to compile it instead of corrupting it at run time.

fn main() {
let mut history = vec![String::from("hi")];
let first = &history[0];
history.push(String::from("again"));
println!("{first}");
}
error[E0502]: cannot borrow `history` as mutable because it is also borrowed as immutable
 --> src/main.rs:4:5
  |
3 |     let first = &history[0];
  |                  ------- immutable borrow occurs here
4 |     history.push(String::from("again"));
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
5 |     println!("{first}");
  |                ----- immutable borrow later used here

The usual fix. Finish using the shared reference before you mutate, or copy out what you need first (.clone() the element).

fn main() {
let mut history = vec![String::from("hi")];
let first = history[0].clone();
history.push(String::from("again"));
println!("{first}");
}

Taught in: 4.3 Borrowing

Link to E0502

E0499Two mutable borrows at once

At any moment you may have many readers or exactly one writer — never two writers. It is the rule that makes data races impossible, and it is checked before the program runs.

fn main() {
let mut cache = String::from("kv");
let a = &mut cache;
let b = &mut cache;
a.push('x');
b.push('y');
}
error[E0499]: cannot borrow `cache` as mutable more than once at a time
 --> src/main.rs:4:13
  |
3 |     let a = &mut cache;
  |             ---------- first mutable borrow occurs here
4 |     let b = &mut cache;
  |             ^^^^^^^^^^ second mutable borrow occurs here
5 |     a.push('x');
  |     - first borrow later used here

The usual fix. Use the first &mut to completion before taking the second, or split the data so each writer owns a different piece.

fn main() {
let mut cache = String::from("kv");
let a = &mut cache;
a.push('x');
let b = &mut cache;
b.push('y');
}

Taught in: 4.4 Borrowing to change

Link to E0499

E0596Borrowed an immutable value as mutable

The method needs &mut self — it changes the value — but the binding was never declared mut.

fn main() {
let history = Vec::<String>::new();
history.push(String::from("x"));
}
error[E0596]: cannot borrow `history` as mutable, as it is not declared as mutable
 --> src/main.rs:3:5
  |
3 |     history.push(String::from("x"));
  |     ^^^^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
2 |     let mut history = Vec::<String>::new();
  |         +++

The usual fix. Declare the binding with let mut.

fn main() {
let mut history = Vec::<String>::new();
history.push(String::from("x"));
}

Link to E0596

E0594Assigned to a field of an immutable binding

Same idea as E0384, one level down: the struct is immutable, so none of its fields can be reassigned.

struct Config {
max_tokens: u32,
}
 
fn main() {
let cfg = Config { max_tokens: 100 };
cfg.max_tokens = 200;
println!("{}", cfg.max_tokens);
}
error[E0594]: cannot assign to `cfg.max_tokens`, as `cfg` is not declared as mutable
 --> src/main.rs:7:5
  |
7 |     cfg.max_tokens = 200;
  |     ^^^^^^^^^^^^^^^^^^^^ cannot assign
  |
help: consider changing this to be mutable
  |
6 |     let mut cfg = Config { max_tokens: 100 };
  |         +++

The usual fix. Make the whole binding mut.

struct Config {
max_tokens: u32,
}
 
fn main() {
let mut cfg = Config { max_tokens: 100 };
cfg.max_tokens = 200;
println!("{}", cfg.max_tokens);
}

Link to E0594

Lifetimes 4

A reference cannot outlive the thing it points at.

E0597Borrowed value does not live long enough

A reference outlived the thing it points at. Python would keep the object alive for you; Rust frees it at the closing brace, so the reference would dangle.

fn main() {
let longest: &str;
{
let reply = String::from("a short-lived reply");
longest = &reply;
}
println!("{longest}");
}
error[E0597]: `reply` does not live long enough
 --> src/main.rs:5:19
  |
4 |         let reply = String::from("a short-lived reply");
  |             ----- binding `reply` declared here
5 |         longest = &reply;
  |                   ^^^^^^ borrowed value does not live long enough
6 |     }
  |     - `reply` dropped here while still borrowed
7 |     println!("{longest}");
  |                ------- borrow later used here

The usual fix. Move the owner to an outer scope, or return an owned value instead of a reference.

fn main() {
let reply = String::from("a short-lived reply");
let longest: &str = &reply;
println!("{longest}");
}

Link to E0597

E0106Missing lifetime specifier

A function returns a reference, but with two inputs the compiler cannot tell which one the output borrows from. It will not guess; you say so with a lifetime name.

fn pick(a: &str, b: &str) -> &str {
if a.len() > b.len() { a } else { b }
}
 
fn main() {
println!("{}", pick("a", "bb"));
}
error[E0106]: missing lifetime specifier
 --> src/main.rs:1:30
  |
1 | fn pick(a: &str, b: &str) -> &str {
  |            ----     ----     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`
help: consider introducing a named lifetime parameter
  |
1 | fn pick<'a>(a: &'a str, b: &'a str) -> &'a str {
  |        ++++     ++          ++          ++

The usual fix. Add a lifetime parameter that ties the output to the inputs it really borrows from: fn pick<'a>(a: &'a str, b: &'a str) -> &'a str.

fn pick<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() { a } else { b }
}
 
fn main() {
println!("{}", pick("a", "bb"));
}

Link to E0106

E0515Returned a reference to a local variable

The local is dropped when the function returns, so a reference to it would point at freed memory.

fn first_word(text: &str) -> &str {
let owned = text.to_uppercase();
&owned[..1]
}
 
fn main() {
println!("{}", first_word("rust"));
}
error[E0515]: cannot return value referencing local variable `owned`
 --> src/main.rs:3:5
  |
3 |     &owned[..1]
  |     ^-----^^^^^
  |     ||
  |     |`owned` is borrowed here
  |     returns a value referencing data owned by the current function

The usual fix. Return the owned value (String) instead of a reference to it.

fn first_word(text: &str) -> String {
let owned = text.to_uppercase();
owned[..1].to_string()
}
 
fn main() {
println!("{}", first_word("rust"));
}

Link to E0515

E0716A temporary value is dropped while borrowed

The right-hand side built a value that lives only until the end of the statement, and you kept a reference to it.

fn main() {
let s: &str = String::from("tmp").as_str();
println!("{s}");
}
error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:2:19
  |
2 |     let s: &str = String::from("tmp").as_str();
  |                   ^^^^^^^^^^^^^^^^^^^         - temporary value is freed at the end of this statement
  |                   |
  |                   creates a temporary value which is freed while still in use
3 |     println!("{s}");
  |                - borrow later used here
  |
help: consider using a `let` binding to create a longer lived value
  |
2 ~     let binding = String::from("tmp");
3 ~     let s: &str = binding.as_str();
  |

The usual fix. Bind the owned value to its own variable first so it lives as long as the reference.

fn main() {
let owned = String::from("tmp");
let s: &str = owned.as_str();
println!("{s}");
}

Link to E0716

Types and patterns 6

Rust converts nothing behind your back and checks every case.

E0308Mismatched types

Rust never converts between types behind your back. A string where a number was declared, an i32 where an f32 was expected, a missing trailing expression: all this one error.

fn main() {
let temperature: f32 = "0.7";
println!("{temperature}");
}
error[E0308]: mismatched types
 --> src/main.rs:2:28
  |
2 |     let temperature: f32 = "0.7";
  |                      ---   ^^^^^ expected `f32`, found `&str`
  |                      |
  |                      expected due to this

The usual fix. Convert explicitly (.parse(), as, .to_string()) or fix the declared type. Read the “expected / found” pair — it names both.

fn main() {
let temperature: f32 = "0.7".parse().unwrap();
println!("{temperature}");
}

Link to E0308

E0063Missing field in a struct literal

Every field of a struct must be given a value when you build it. There are no optional fields — if a value can be absent, its type is Option<T> and you write None.

struct ChatMessage {
role: String,
content: String,
}
 
fn main() {
let m = ChatMessage { role: String::from("user") };
println!("{}", m.role);
}
error[E0063]: missing field `content` in initializer of `ChatMessage`
 --> src/main.rs:7:13
  |
7 |     let m = ChatMessage { role: String::from("user") };
  |             ^^^^^^^^^^^ missing `content`

The usual fix. Add the missing field, or use struct update syntax (..Default::default()).

struct ChatMessage {
role: String,
content: String,
}
 
fn main() {
let m = ChatMessage {
role: String::from("user"),
content: String::from("hello"),
};
println!("{} {}", m.role, m.content);
}

Link to E0063

E0004Non-exhaustive match

A match must cover every possible value. This is the feature that makes adding an enum variant safe: the compiler lists every place you forgot to handle the new case.

enum Role {
System,
User,
Assistant,
}
 
fn label(r: Role) -> &'static str {
match r {
Role::System => "system",
Role::User => "user",
}
}
 
fn main() {
println!("{}", label(Role::Assistant));
}
error[E0004]: non-exhaustive patterns: `Role::Assistant` not covered
  --> src/main.rs:8:11
   |
 8 |     match r {
   |           ^ pattern `Role::Assistant` not covered
   |
note: `Role` defined here
  --> src/main.rs:1:6
   |
 1 | enum Role {
   |      ^^^^
...
 4 |     Assistant,
   |     --------- not covered
   = note: the matched value is of type `Role`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
   |
10 ~         Role::User => "user",
11 ~         Role::Assistant => todo!(),
   |

The usual fix. Add the missing arm, or a deliberate _ catch-all if you truly mean “everything else”.

enum Role {
System,
User,
Assistant,
}
 
fn label(r: Role) -> &'static str {
match r {
Role::System => "system",
Role::User => "user",
Role::Assistant => "assistant",
}
}
 
fn main() {
println!("{}", label(Role::Assistant));
}

Link to E0004

E0072Recursive type has infinite size

A type that contains itself directly has no finite size. Put the recursion behind a pointer, which has a fixed size.

struct Plan {
step: String,
next: Option<Plan>,
}
 
fn main() {}
error[E0072]: recursive type `Plan` has infinite size
 --> src/main.rs:1:1
  |
1 | struct Plan {
  | ^^^^^^^^^^^
2 |     step: String,
3 |     next: Option<Plan>,
  |                  ---- recursive without indirection
  |
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
  |
3 |     next: Option<Box<Plan>>,
  |                  ++++    +

The usual fix. Wrap the recursive field in Box<…>.

struct Plan {
step: String,
next: Option<Box<Plan>>,
}
 
fn main() {
let p = Plan { step: String::from("a"), next: None };
println!("{}", p.step);
}

Link to E0072

E0369Binary operator not supported for this type

Joining two &str with + is not defined — only String + &str is, because the left side must be an owned buffer to extend.

fn main() {
let prompt = "system: " + "be brief";
println!("{prompt}");
}
error[E0369]: cannot add `&str` to `&str`
 --> src/main.rs:2:29
  |
2 |     let prompt = "system: " + "be brief";
  |                  ---------- ^ ---------- &str
  |                  |          |
  |                  |          `+` cannot be used to concatenate two `&str` strings
  |                  &str
  |
  = note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
  |
2 |     let prompt = "system: ".to_owned() + "be brief";
  |                            +++++++++++

The usual fix. Use format!, or make the left side an owned String.

fn main() {
let prompt = format!("{}{}", "system: ", "be brief");
println!("{prompt}");
}

Link to E0369

E0282Type annotations needed

Nothing in the program pins down what type a value has, so inference cannot finish. Say the type once and it can.

fn main() {
let embedding = Vec::new();
println!("{}", embedding.len());
}
error[E0282]: type annotations needed for `Vec<_>`
 --> src/main.rs:2:9
  |
2 |     let embedding = Vec::new();
  |         ^^^^^^^^^   ---------- type must be known at this point
  |
help: consider giving `embedding` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let embedding: Vec<T> = Vec::new();
  |                  ++++++++

The usual fix. Annotate the binding (Vec<f32>) or use a turbofish (Vec::<f32>::new()).

fn main() {
let embedding: Vec<f32> = Vec::new();
println!("{}", embedding.len());
}

Link to E0282

Traits and closures 5

What a type can do, and which promise a closure is making.

E0277A trait bound is not satisfied

You used a value somewhere that needs a capability — Ord to sort, Display to print, Send to cross threads — and the type does not have it. Also what you see when ? is used in a function that returns ().

fn main() {
let n: i32 = "42".parse()?;
println!("{n}");
}
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/main.rs:2:30
  |
1 | fn main() {
  | --------- this function should return `Result` or `Option` to accept `?`
2 |     let n: i32 = "42".parse()?;
  |                              ^ cannot use the `?` operator in a function that returns `()`
  |
help: consider adding return type
  |
1 ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
2 |     let n: i32 = "42".parse()?;
3 |     println!("{n}");
4 +     Ok(())
  |

The usual fix. Read the “the trait … is not implemented for …” line, then implement or derive the trait, change the type, or change what the function returns.

fn main() -> Result<(), std::num::ParseIntError> {
let n: i32 = "42".parse()?;
println!("{n}");
Ok(())
}

Link to E0277

E0046Missing trait item in an impl

The trait promises methods; your impl has to supply every one that has no default body.

trait LlmProvider {
fn complete(&self, prompt: &str) -> String;
}
 
struct Echo;
 
impl LlmProvider for Echo {}
 
fn main() {}
error[E0046]: not all trait items implemented, missing: `complete`
 --> src/main.rs:7:1
  |
2 |     fn complete(&self, prompt: &str) -> String;
  |     ------------------------------------------- `complete` from trait
...
7 | impl LlmProvider for Echo {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `complete` in implementation

The usual fix. Implement each missing method — the error names them.

trait LlmProvider {
fn complete(&self, prompt: &str) -> String;
}
 
struct Echo;
 
impl LlmProvider for Echo {
fn complete(&self, prompt: &str) -> String {
prompt.to_string()
}
}
 
fn main() {
println!("{}", Echo.complete("hi"));
}

Link to E0046

E0038The trait is not dyn-compatible

You wrote dyn Trait, but the trait has a method the compiler cannot call through a pointer — it returns Self, or is generic. Static dispatch can do it; a vtable cannot.

trait Tool {
fn duplicate(&self) -> Self;
}
 
fn main() {
let _tools: Vec<Box<dyn Tool>> = Vec::new();
}
error[E0038]: the trait `Tool` is not dyn compatible
 --> src/main.rs:6:29
  |
6 |     let _tools: Vec<Box<dyn Tool>> = Vec::new();
  |                             ^^^^ `Tool` is not dyn compatible
  |
note: for a trait to be dyn compatible it needs to allow building a vtable
      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 --> src/main.rs:2:28
  |
1 | trait Tool {
  |       ---- this trait is not dyn compatible...
2 |     fn duplicate(&self) -> Self;
  |                            ^^^^ ...because method `duplicate` references the `Self` type in its return type
  = help: consider moving `duplicate` to another trait

The usual fix. Remove or where Self: Sized-gate the offending method, or use generics instead of dyn.

trait Tool {
fn name(&self) -> String;
}
 
fn main() {
let _tools: Vec<Box<dyn Tool>> = Vec::new();
}

Link to E0038

E0525Closure is FnOnce but Fn was required

The closure moves something out of its captures, so it can only run once — but the function you passed it to wants to call it repeatedly.

fn call_twice<F: Fn()>(f: F) {
f();
f();
}
 
fn main() {
let prompt = String::from("hi");
let consume = move || drop(prompt);
call_twice(consume);
}
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
 --> src/main.rs:8:19
  |
8 |     let consume = move || drop(prompt);
  |                   ^^^^^^^      ------ closure is `FnOnce` because it moves the variable `prompt` out of its environment
  |                   |
  |                   this closure implements `FnOnce`, not `Fn`
9 |     call_twice(consume);
  |     ---------- ------- the requirement to implement `Fn` derives from here
  |     |
  |     required by a bound introduced by this call
  |
note: required by a bound in `call_twice`
 --> src/main.rs:1:18
  |
1 | fn call_twice<F: Fn()>(f: F) {
  |                  ^^^^ required by this bound in `call_twice`

The usual fix. Stop consuming the capture (borrow or clone it inside), or accept FnOnce if one call is enough.

fn call_twice<F: Fn()>(f: F) {
f();
f();
}
 
fn main() {
let prompt = String::from("hi");
call_twice(move || println!("{prompt}"));
}

Link to E0525

E0599No method with that name for this type

The method does not exist on this type — often because it lives on a trait you have not brought into scope, or on a different type (Option vs its contents).

fn main() {
let v = vec![1, 2, 3];
v.append_item(4);
}
error[E0599]: no method named `append_item` found for struct `Vec<{integer}>` in the current scope
 --> src/main.rs:3:7
  |
3 |     v.append_item(4);
  |       ^^^^^^^^^^^
  |
help: there is a method `append` with a similar name
  |
3 -     v.append_item(4);
3 +     v.append(4);
  |

The usual fix. Check the type with the hover text in your editor; import the trait; or unwrap the Option/Result first.

fn main() {
let mut v = vec![1, 2, 3];
v.push(4);
println!("{}", v.len());
}

Link to E0599

Threads and async 1

Work that outlives the function that started it must own what it uses.

E0373Closure may outlive the current function

A spawned thread can run after this function returns, so it cannot merely borrow local variables. It has to own them.

use std::thread;
 
fn main() {
let batch = vec![1.0f32, 2.0];
let h = thread::spawn(|| println!("{}", batch.len()));
h.join().unwrap();
}
error[E0373]: closure may outlive the current function, but it borrows `batch`, which is owned by the current function
 --> src/main.rs:5:27
  |
5 |     let h = thread::spawn(|| println!("{}", batch.len()));
  |                           ^^                ----- `batch` is borrowed here
  |                           |
  |                           may outlive borrowed value `batch`
  |
note: function requires argument type to outlive `'static`
 --> src/main.rs:5:13
  |
5 |     let h = thread::spawn(|| println!("{}", batch.len()));
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `batch` (and any other referenced variables), use the `move` keyword
  |
5 |     let h = thread::spawn(move || println!("{}", batch.len()));
  |                           ++++

The usual fix. Add move to the closure so it takes ownership of what it uses.

use std::thread;
 
fn main() {
let batch = vec![1.0f32, 2.0];
let h = thread::spawn(move || println!("{}", batch.len()));
h.join().unwrap();
}

Link to E0373

Names and imports 2

The compiler could not find what you named.

E0425Cannot find a value in scope

The name does not exist where you used it: a typo, a missing let, or a variable declared inside a block you have already left.

fn main() {
let model_name = "tiny";
println!("{}", modle_name);
}
error[E0425]: cannot find value `modle_name` in this scope
 --> src/main.rs:3:20
  |
3 |     println!("{}", modle_name);
  |                    ^^^^^^^^^^
  |
help: a local variable with a similar name exists
  |
3 -     println!("{}", modle_name);
3 +     println!("{}", model_name);
  |

The usual fix. Check the spelling and the scope the name was declared in.

fn main() {
let model_name = "tiny";
println!("{}", model_name);
}

Taught in: 1.3 Printing and comments

Link to E0425

E0433Failed to resolve: use of an undeclared type

Standard-library types outside the prelude have to be imported. HashMap is not in scope until you say where it lives.

fn main() {
let vocab = HashMap::new();
let _: &std::collections::HashMap<String, u32> = &vocab;
}
error[E0433]: cannot find type `HashMap` in this scope
 --> src/main.rs:2:17
  |
2 |     let vocab = HashMap::new();
  |                 ^^^^^^^ use of undeclared type `HashMap`
  |
help: consider importing this struct
  |
1 + use std::collections::HashMap;
  |

The usual fix. Add use std::collections::HashMap;.

use std::collections::HashMap;
 
fn main() {
let vocab: HashMap<String, u32> = HashMap::new();
println!("{}", vocab.len());
}

Link to E0433

Learn Rust by building a chat app · error atlas · compiler output from rustc 1.99.0 (b940084d7 2026-09-28) (edition 2024) · Vibe Engines · 2026