Rust: the `?` operator could not convert the error (E0277)
The ? operator converts the error with From, and no such conversion exists between the error you produced and the one your function returns. It is the most common friction point when a function starts touching two libraries with their own error types.
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.
// Define the conversion once with thiserror
#[derive(thiserror::Error, Debug)]
pub enum AppError {
#[error("io: {0}")]
Io(#[from] std::io::Error),
#[error("parse: {0}")]
Parse(#[from] serde_json::Error),
}
// Application code that does not need typed errors
fn main() -> anyhow::Result<()> {
let cfg: Config = serde_json::from_str(&std::fs::read_to_string("c.json")?)?;
Ok(())
}
// One off: convert at the call site
.map_err(|e| AppError::Other(e.to_string()))?
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 `*self` as mutable because it is also borrowed as immutableThe immutable borrow is usually hidden in an argument: self.push(self.len()) borrows self 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.