Skip to content
Select theme

How to fix error E0384: cannot assign twice to immutable variable

Short answer: the variable was declared without mut. Change let x = 5; to let mut x = 5; — mut goes on the declaration, and nowhere else.

Compiling that with cargo build prints:

error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:3:5
|
2 | let x = 5;
| - first assignment to `x`
3 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut x = 5;
| +++

The help block is the whole fix: put mut after let on the line where the variable is declared.

The message says assign twice, which sounds odd when you only wrote one =. The reason is that let x = 5; is itself an assignment — the first one. Rust gives every let binding exactly one assignment unless you mark it mut.

You can see this by splitting the declaration and the assignment apart:

That runs and prints 5. No mut needed, because it is still the first assignment. A second x = 6; after it is what E0384 objects to.

This prints 6. Compound assignments trigger the same error too: total += 5; on a let total = 0; binding fails with E0384 just like total = 5; would, and the same mut fixes it.

mut always sits with the binding, not the assignment. On a let line:

let mut total = 0;

On a function parameter, when the function body wants to reuse its own copy:

This prints 10. mut n: u32 means the function owns its own copy and is allowed to change it — n /= 10 needs it. The caller passes a plain value as usual; the caller’s variable is unaffected either way, because u32 is copied, not moved.

For “give the variable a new value”, Rust offers two tools, and they are not the same:

This prints 6. Shadowing declares a fresh variable each time; the old one still existed until the new one covered it up. That is why the type is allowed to change from i32 to String.

Pick shadowing when the new value replaces the old for good — conversions, re-parsing, the usual let input = input.trim(); chain. Pick mut when you are building one value up in place: counters, accumulators, loops that mutate as they go. If the variable’s type never changes and every “reassignment” is really a step in a computation, mut is the honest spelling.

Two neighbours that look identical but carry different codes:

  • Assigning to a field of an immutable struct — p.x = 10; where p is let p = ... — fails with E0594 (cannot assign to p.x, as p is not declared as mutable). Same missing-mut cause, different message.
  • Calling a method that needs &mut on an immutable binding is E0596, and it is about borrowing rather than assignment.
  • E0382 — borrow of moved value
  • E0594 — cannot assign to a field of an immutable struct
  • E0596 — cannot borrow as mutable, as it is not declared as mutable