Rust: cannot borrow `*self` as mutable because it is also borrowed as immutable
The immutable borrow is usually hidden in an argument: self.push(self.len()) borrows self to evaluate the argument while the method call already holds a mutable borrow. Borrows end at their last use under NLL, so the fix is nearly always to finish the read before starting the write rather than to restructure the type.
Quick fix
Read the commands before running them. Anything that restarts a service, deletes data or changes permissions should be tried on a non-production system first.
// Rejected: the argument is evaluated while &mut self is live
self.items.push(self.items.len());
// Accepted: read first, then write
let n = self.items.len();
self.items.push(n);
// Borrowing two fields at once is fine, borrowing self twice is not
let Self { input, output } = self; // split borrow
output.extend(input.iter().copied());
// Inside a loop, collect the reads before mutating
let keys: Vec<_> = self.map.keys().cloned().collect();
for k in keys { self.map.remove(&k); }
// std::mem::take lets you own a field for the duration
let mut buf = std::mem::take(&mut self.buffer);
self.flush(&mut buf);
self.buffer = buf;
How to diagnose Rust errors
Rust's compiler errors are unusually helpful. They are closer to a code review than an error message. Almost all of them come from ownership (a value was moved and then used), borrowing (two mutable borrows, or a borrow outliving its owner), or trait resolution (the required bound is not satisfied). The productive habit is to read the error's notes and help sections in full and run rustc --explain on the code.
If the quick fix above does not resolve it, work through these steps. They apply to this whole class of error, not just to this one message, which is usually what saves the time.
- Run
rustc --explain E0502(or whichever code) for a worked explanation of the rule you violated. - For borrow conflicts, shorten the borrow's scope first, introducing a block or binding the intermediate result, before reaching for
Rc<RefCell<T>>. - For moved-value errors, decide deliberately: clone (cost), borrow (lifetime), or restructure so ownership flows one way. Cloning to silence the compiler is fine early and worth revisiting later.
- For trait errors, read which bound is missing and where it is required.
cargo tree -dfinds duplicate crate versions, which cause "trait not implemented" errors between two identical-looking types. - Use
cargo clippyroutinely; it catches idiom problems that later become borrow-checker fights.
Tools worth reaching for
rustc --explaincargo clippycargo tree -dcargo expandRUST_BACKTRACE=1
Authoritative references
Primary documentation for this error, worth reading before applying any fix in production.
Related Rust errors
- cannot borrow as mutable, as it is behind a & referenceAttempting to mutate data through a shared (immutable) reference. Rust enforces either one…
- cannot move out of borrowed contentAttempting to move a value out of a reference, which would invalidate the borrow. Rust's…
- Cargo: Blocking waiting for file lock on package cacheCargo takes an exclusive lock on its home directory so two builds cannot corrupt the…
- Cargo: lock file version requires a newer version of CargoCargo.lock carries a format version. A newer toolchain wrote a version this Cargo cannot…
- failed to select a version for XCargo cannot resolve a compatible set of dependency versions. Two or more crates require…
- mismatched types: expected X, found YThe compiler expected one type but found another. Common with integer types, string types…
- Rust: called `Option::unwrap()` on a `None` valueunwrap says the value is definitely there, and it was not, so the thread panicked at that…
- Rust: cannot borrow `x` as mutable more than once at a timeRust's ownership rules prevent multiple mutable references to the same data simultaneously to…
Browse other categories
- HTTP 494xx client errors, 5xx server errors, redirects, headers and protocol problems.
- JavaScript 42npm resolution, async pitfalls, hydration, memory limits and runtime type…
- Database 41Connections, deadlocks, constraints, replication and memory limits.
- AI 35Rate limits, context windows, GPU memory and model-serving failures.
- Network 35Refused connections, timeouts, resets, MTU problems and port exhaustion.
- Python 35Imports, virtual environments, encoding, concurrency and dependency conflicts.
- Kubernetes 34CrashLoopBackOff, ImagePullBackOff, OOMKilled, RBAC, scheduling and storage.
- Docker 27Daemon connectivity, disk space, image pulls, ports and architecture mismatches.
- System 26Disk space, systemd units, file descriptors, OOM killer and scheduled jobs.
- Cloud 25IAM permissions, quotas, service limits and credential failures.
- Security 25JWT validation, CSRF, OAuth grants, SELinux, SSH host keys and CSP.
- TLS 24Untrusted authorities, expiry, hostname mismatch, chains and cipher negotiation.
Something missing or wrong?
This entry is maintained by hand. If the fix is out of date, incomplete, or you have a better one, email a correction and it will be reviewed.