Rust Error E0499: Cannot Borrow as Mutable More Than Once at a Time
Error E0499 means you tried to have two mutable references (&mut) to the same value at the same time. It’s one of the most common borrow checker errors, and the fix is usually small: often you just need to move one line. (Looking for a different error? See the compiler errors overview.)
The error message
Section titled “The error message”error[E0499]: cannot borrow `balance` as mutable more than once at a time --> src/main.rs:5:20 |4 | let deposit = &mut balance; | ------------ first mutable borrow occurs here5 | let withdraw = &mut balance; | ^^^^^^^^^^^^ second mutable borrow occurs here6 |7 | *deposit += 50; | -------------- first borrow later used hereHere is the program that produces it:
fn main() { let mut balance = 100;
let deposit = &mut balance; let withdraw = &mut balance;
*deposit += 50; *withdraw -= 30;
println!("Balance: {balance}");}What it means
Section titled “What it means”The compiler points at three places, and together they tell the whole story:
- Line 4:
depositbecomes a mutable borrow ofbalance. - Line 5:
withdrawtries to become a second mutable borrow ofbalance. - Line 7:
depositis still used after line 5. So the first borrow is still alive when the second one starts.
That third label is the important one. Two &mut borrows are only a problem when their lifetimes overlap. If deposit were finished before line 5, there would be no error.
Think of a shared document with one “edit” key. Whoever holds the key can change the document. Rust won’t make a copy of the key: the second person must wait until the first one gives it back.
Why Rust does this
Section titled “Why Rust does this”Rust’s borrowing rule is: at any moment you can have many readers (&) or one writer (&mut), never more than one writer. A &mut reference is a promise: “while I exist, nobody else can touch this value.”
That promise prevents real bugs. If two pieces of code could change the same value at once, one could resize a Vec while the other still points into its old memory. In other languages that’s a crash or silent data corruption. Across threads, it’s a data race.
Because of this rule, the compiler can be sure that a &mut is the only way to reach the data while it lives. You get that safety with zero runtime cost. The price is that sometimes you have to tell the compiler more clearly that your two borrows don’t really clash.
How to fix it
Section titled “How to fix it”Fix 1: Finish the first borrow before starting the second
Section titled “Fix 1: Finish the first borrow before starting the second”Choose this first. It fixes most E0499 errors. A borrow lasts until its last use, not until the end of the block. So do all the work with the first reference, then create the second one:
fn main() { let mut balance = 100;
let deposit = &mut balance; *deposit += 50; // last use of `deposit`: its borrow ends here
let withdraw = &mut balance; // ✅ nobody else is borrowing now *withdraw -= 30;
println!("Balance: {balance}");}Output:
Balance: 120Often you don’t need the extra variables at all: balance += 50; then balance -= 30; works just as well.
Fix 2: Borrow parts that don’t overlap
Section titled “Fix 2: Borrow parts that don’t overlap”Sometimes you really need two &mut at once, but they point at different parts of the data. The compiler can’t always see that, so you show it.
For two elements of a Vec or slice, tasks[0] and tasks[1] both borrow the whole tasks. Use split_at_mut to cut it into two halves that are guaranteed not to overlap:
fn main() { let mut tasks = vec![String::from("write"), String::from("test")];
// Split the Vec into two halves that don't overlap let (left, right) = tasks.split_at_mut(1); let first = &mut left[0]; let second = &mut right[0];
std::mem::swap(first, second); println!("{tasks:?}");}Output:
["test", "write"](For swapping specifically, tasks.swap(0, 1) is even simpler. split_at_mut is for when you need both references for real work.)
For a struct, the same error appears when you call two methods that each take &mut self, like p.name_mut() and p.score_mut(). Each call borrows the whole struct. If you borrow the fields directly instead, the compiler sees they are separate:
struct Player { name: String, score: u32,}
fn main() { let mut p = Player { name: String::from("Ferris"), score: 0 };
// Borrow the fields directly, not through methods let name = &mut p.name; let score = &mut p.score;
name.push_str(" the Crab"); *score += 10; println!("{} has {} points", p.name, p.score);}Output:
Ferris the Crab has 10 pointsFix 3: Use indices instead of holding references
Section titled “Fix 3: Use indices instead of holding references”A classic: you loop over a Vec with iter_mut() and also try to push to it inside the loop. The iterator holds a &mut for the whole loop, so push is a second one:
fn main() { let mut queue = vec![1, 2, 3]; for job in queue.iter_mut() { *job *= 10; queue.push(*job); // ❌ E0499: `queue` is already borrowed by iter_mut() }}When the loop must change the collection itself, loop over positions instead. An index is just a number, so it doesn’t borrow anything:
fn main() { let mut queue = vec![1, 2, 3];
// Loop over positions instead of holding a reference into `queue` for i in 0..queue.len() { queue[i] *= 10; let job = queue[i]; queue.push(job); }
println!("{queue:?}");}Output:
[10, 20, 30, 10, 20, 30]0..queue.len() is calculated once, before the loop starts, so the new items are not visited again. Each queue[i] borrow lasts for one line only.
Fix 4: RefCell (last resort)
Section titled “Fix 4: RefCell (last resort)”RefCell moves the borrow check from compile time to run time. You can call borrow_mut() without a mut variable, as long as no two mutable borrows are alive at the same moment:
use std::cell::RefCell;
fn main() { let balance = RefCell::new(100); // note: no `mut` needed
*balance.borrow_mut() += 50; // borrow, change, borrow ends at `;` *balance.borrow_mut() -= 30;
println!("Balance: {}", balance.borrow());}Output:
Balance: 120Be honest with yourself here: RefCell doesn’t remove the rule, it only checks it later. If you keep two borrow_mut() guards alive at once, the program compiles but panics when it runs:
use std::cell::RefCell;
fn main() { let balance = RefCell::new(100);
let mut deposit = balance.borrow_mut(); let mut withdraw = balance.borrow_mut(); // 💥 `deposit` is still alive
*deposit += 50; *withdraw -= 30;}thread 'main' (12345) panicked at src/main.rs:7:32:RefCell already borrowedSo reach for RefCell only when the data really is shared (for example inside Rc<RefCell<T>>) and Fixes 1–3 don’t fit. It’s not a way to silence the compiler.
Where you’ll usually see it
Section titled “Where you’ll usually see it”- Storing
&mutin a loop.handles.push(&mut counter)inside aforloop fails with “mutably borrowed here in the previous iteration of the loop”. Each turn of the loop adds another&mutto the same value. Fix: store indices or owned values, or change the value directly in the loop. - Two
get_mutcalls on aHashMap.let a = stock.get_mut("apples")thenlet p = stock.get_mut("pears")borrowsstocktwice. Fix: finish withabefore callingget_mutagain, or usestock.get_disjoint_mut(["apples", "pears"])to get both at once. - Two closures that change the same variable.
let mut inc = || count += 1;andlet mut inc2 = || count += 2;each hold a&mut countfor as long as they live. Fix: use one closure, or call the first one for the last time before creating the second. See Closures.
Related errors
Section titled “Related errors”- E0502: cannot borrow as mutable because it is also borrowed as immutable: the same idea, but one of the borrows is a read-only
&. - E0382: borrow of moved value: you used a value after it was moved somewhere else.
- E0106: missing lifetime specifier: Rust needs to know how long a returned reference lives.
- All compiler errors: the full list of error pages.
Quick check
Section titled “Quick check”Quick check
1. When does Rust report E0499?
2. You create let a = &mut v;, use a for the last time, then create let b = &mut v;. What happens?
3. Which tool lets you get two &mut references to different elements of the same slice?
Score: 0 / 3
Read more
Section titled “Read more”- E0499 — Rust error codes index: the official explanation of this error, with a minimal example.
- References and Borrowing — The Rust Book: the chapter that introduces the “only one
&mutat a time” rule. - Splitting Borrows — The Rustonomicon: why struct fields can be borrowed separately but slice elements can’t, and how
split_at_mutworks. - RefCell and Interior Mutability — The Rust Book: when moving borrow checks to run time is the right call.