Quick answer
You used a value after its ownership moved — it was assigned away, passed to a function by value, or returned. For a non-Copy type that invalidates the original binding. Fix it by borrowing (&value) instead of moving, deriving Copy for small types, or clone()ing only when both sides truly need ownership.
The exact error string
error[E0382]: borrow of moved value: `s`
--> src/main.rs:4:20
|
2 | let s = String::from("hi");
| - move occurs because `s` has type `String`,
| which does not implement the `Copy` trait
3 | let t = s; // value moved here
| -
4 | println!("{}", s); // value borrowed here after move
| ^ value borrowed here after move
How to read it
Rust gives you three coordinates: "move occurs because ..." (the type isn't Copy), "value moved here" (the line that took ownership), and "value borrowed here after move" (the now-illegal use). The fix is almost always at that third line — make it borrow rather than consume.
Cause 1: moved by assignment, then used
let s = String::from("hi");
let t = s; // ❌ s moved into t
println!("{} {}", s, t);
// ✅ borrow if you only need to read both
let s = String::from("hi");
let t = &s; // t borrows, s still owns
println!("{} {}", s, t);
Cause 2: moved into a function, then used
fn show(v: Vec<i32>) { println!("{:?}", v); }
let nums = vec![1, 2, 3];
show(nums); // ❌ nums moved into show()
println!("{}", nums.len());
// ✅ take a reference instead of ownership
fn show(v: &[i32]) { println!("{:?}", v); }
show(&nums);
println!("{}", nums.len());
Cause 3: moved by a for loop or closure
let words = vec![String::from("a"), String::from("b")];
for w in words { println!("{}", w); } // moves & consumes words
println!("{}", words.len()); // ❌ value borrowed after move
// ✅ iterate by reference
for w in &words { println!("{}", w); }
println!("{}", words.len()); // words still owned
When clone or Copy is the right answer
// Small, cheap, value-semantics type -> derive Copy
#[derive(Clone, Copy)]
struct Point { x: i32, y: i32 }
// Both sides genuinely need an owned String -> clone explicitly
let s = String::from("hi");
let t = s.clone(); // deliberate deep copy
println!("{} {}", s, t);
Common causes at a glance
| What moved the value | Symptom | Fix |
|---|---|---|
let t = s; | used s afterward | let t = &s; |
f(s) by value | used s after the call | take &s / &mut s |
for x in vec | vec unusable after loop | for x in &vec |
move closure | captured value gone | capture by reference |
| returning a field | partial move of a struct | return a clone or restructure |
Debugging checklist
- ✓ Find "value moved here" — that line took ownership
- ✓ Find "value borrowed here after move" — fix this use to borrow
- ✓ Does the callee only read? Change it to take
&T - ✓ Iterating? Use
&vec/.iter()instead ofvec - ✓ Small POD type?
#[derive(Clone, Copy)]. Otherwiseclone()deliberately
Frequently Asked Questions
What does 'borrow of moved value' (E0382) mean?
You used a value after its ownership was moved elsewhere — by assigning it, passing it to a function by value, or returning it. Once a non-Copy value moves, the original binding is invalid, so any later use is rejected at compile time.
What is the difference between move and borrow?
A move transfers ownership: the source can no longer be used. A borrow (&value or &mut value) lends temporary access without transferring ownership, so the original stays usable afterward. Most E0382 fixes are about borrowing instead of moving.
Should I just call .clone() to fix E0382?
clone() works and is sometimes the right call, but it copies the whole value at runtime. Prefer a borrow (&) when the callee only needs to read. Reach for clone only when both sides genuinely need to own a copy.
Why don't integers cause E0382?
Types that implement the Copy trait (integers, floats, bool, char, and tuples/arrays of them) are bit-copied instead of moved, so the original stays valid. String, Vec, Box, and most structs are not Copy, so they move.
Why does moving happen inside a loop or closure?
A for loop over a Vec by value moves each element (and consumes the Vec). A closure that captures a value by move (or a move closure) takes ownership. Iterate with &vec / vec.iter(), or capture by reference, to avoid the move.
How do I read the E0382 message?
Rust points at three spots: where the value was moved ("value moved here"), why the type can't Copy ("move occurs because ... does not implement the Copy trait"), and where you used it afterward ("value borrowed here after move"). Fix the middle use so it borrows.
More language & runtime errors
Browse the full reference for Rust, Go, Node.js, Python, and database errors — exact message, cause, and fix.