E0301
Rust Programming Language
Severity: ModerateWhat Does This Error Mean?
E0301 means you tried to borrow something immutably (for reading) while it is already borrowed mutably (for writing), or vice versa. Rust's borrow checker enforces one rule: you can have EITHER one mutable borrow OR multiple immutable borrows — never both at the same time. This prevents data races and use-after-modification bugs. The fix is to ensure the mutable borrow ends before taking an immutable borrow.
Affected Models
- Rust 1.0 and later
- All Rust editions
Common Causes
- Holding a mutable reference to a value and then trying to read that value elsewhere
- Passing a mutable reference to a function and then trying to use the original variable
- A mutable borrow is still in scope when an immutable borrow is attempted
- Iterator invalidation pattern — modifying a collection while iterating over it
- Closure captures a mutable borrow while the outer scope still needs to read the value
How to Fix It
-
Find where the mutable borrow starts and where it ends. In Rust, a borrow ends at the last place it is used (with NLL — Non-Lexical Lifetimes, enabled since Rust 2018).
If the mutable borrow is held in a variable (let mut_ref = &mut x), it lasts until mut_ref is last used.
-
Restructure the code so the mutable borrow finishes before the immutable borrow begins. Use a block scope to force the mutable borrow to end early.
Example: { let r = &mut x; *r = 5; } // mutable borrow ends here let s = &x; // immutable borrow is now safe
-
If you need to read from a value after mutating it, finish all mutations first and then do all the reads.
Batch your mutations together, then batch your reads. Alternating mutate/read/mutate/read is the pattern that causes borrow conflicts.
-
For collections, do not hold an iterator (immutable borrow) while modifying the collection (mutable borrow). Collect results first, then modify.
Collect items to change into a Vec, then loop over that Vec to make the changes — this separates the read phase from the write phase.
-
Consider using Cell<T> or RefCell<T> for interior mutability — they allow mutation through an immutable reference by moving borrow checks to runtime.
RefCell<T> enables mutable access via borrow_mut() even with only an immutable reference. Use with care — runtime panics instead of compile errors if borrows conflict.
When to Call a Professional
Borrow errors are Rust's core safety mechanism — they prevent bugs that crash programs in other languages. The fix is to restructure the code so mutable and immutable borrows do not overlap in time. Rust's error messages are detailed and usually show exactly where both borrows occur.
Frequently Asked Questions
What is the borrow checker in Rust?
The borrow checker is a part of the Rust compiler that tracks who owns and borrows each value. It enforces Rust's ownership rules at compile time, preventing memory safety bugs without a garbage collector. The key rule: you can have one mutable borrow OR any number of immutable borrows at a time — never both simultaneously. This rule prevents data races, use-after-free bugs, and iterator invalidation.
Why does Rust not allow mutable and immutable borrows at the same time?
Because it prevents a whole class of bugs where one piece of code is reading a value while another piece is changing it. If you are reading something while it is being mutated, you might see inconsistent or partially-updated data. By preventing this at compile time, Rust guarantees that any code that compiles is free from data races. This is one of Rust's core safety guarantees.
What is RefCell and when should I use it?
RefCell<T> is a type that moves Rust's borrow checks from compile time to runtime. It allows you to get a mutable borrow even through an immutable reference — called interior mutability. Use it when you need to share data and mutate it, but the borrow checker's static rules are too restrictive for your design. If two borrows conflict at runtime (both try to mutate at the same time), RefCell panics instead of crashing with undefined behavior.