Skip to content

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.)

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 here
5 | let withdraw = &mut balance;
| ^^^^^^^^^^^^ second mutable borrow occurs here
6 |
7 | *deposit += 50;
| -------------- first borrow later used here

Here 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}");
}

The compiler points at three places, and together they tell the whole story:

  1. Line 4: deposit becomes a mutable borrow of balance.
  2. Line 5: withdraw tries to become a second mutable borrow of balance.
  3. Line 7: deposit is 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.

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.

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: 120
▶ Try it Yourself

Often you don’t need the extra variables at all: balance += 50; then balance -= 30; works just as well.

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"]
▶ Try it Yourself

(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 points
▶ Try it Yourself

Fix 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]
▶ Try it Yourself

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.

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: 120
▶ Try it Yourself

Be 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 borrowed

So 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.

  • Storing &mut in a loop. handles.push(&mut counter) inside a for loop fails with “mutably borrowed here in the previous iteration of the loop”. Each turn of the loop adds another &mut to the same value. Fix: store indices or owned values, or change the value directly in the loop.
  • Two get_mut calls on a HashMap. let a = stock.get_mut("apples") then let p = stock.get_mut("pears") borrows stock twice. Fix: finish with a before calling get_mut again, or use stock.get_disjoint_mut(["apples", "pears"]) to get both at once.
  • Two closures that change the same variable. let mut inc = || count += 1; and let mut inc2 = || count += 2; each hold a &mut count for as long as they live. Fix: use one closure, or call the first one for the last time before creating the second. See Closures.

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