Rust E0004/E0658 — Match Not Exhaustive
Resolve non-exhaustive match errors by covering every variant or adding a wildcard arm, and understand why adding an enum variant breaks callers.
Symptoms
- error[E0004]: non-exhaustive patterns: `Variant(_)` not covered
- The match worked until a new enum variant was added
- The compiler suggests the missing arms
Possible causes
- A new enum variant was added and the existing match was not updated
- A wildcard arm was removed, exposing uncovered variants
- Matching on a reference destructures differently than expected
Diagnosis steps
Read the suggested patterns
cargo build 2>&1 | sed -n "/E0004/,/^$/p"Interpretation
rustc lists the uncovered variants, so you can add exactly those arms.
Enumerate variants that must be handled
grep -n "^pub enum\|^enum" -A 12 src/lib.rsInterpretation
Seeing the full enum confirms which variants are missing from the match.
Root cause
Rust requires a match to handle every possible value of the scrutinee type. Adding a variant to an enum makes previously exhaustive matches non-exhaustive, which the compiler reports as E0004 with the missing patterns.
Fix
Add an arm for each missing variant, or add a deliberate wildcard `_ =>` when the default behavior is truly correct; prefer explicit arms so future variants are caught at compile time.
Risk note
A catch-all wildcard silently absorbs new variants, defeating the safety the enum was meant to give.
Verify the fix
cargo build succeeds and a test constructs each variant and asserts the expected branch is taken.
Symptoms
When you hit “Rust E0004/E0658 — Match Not Exhaustive”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.
Observed symptoms include:
- error[E0004]: non-exhaustive patterns:
Variant(_)not covered - The match worked until a new enum variant was added
- The compiler suggests the missing arms
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Read the suggested patterns
cargo build 2>&1 | sed -n "/E0004/,/^$/p"
rustc lists the uncovered variants, so you can add exactly those arms.
Step 2: Enumerate variants that must be handled
grep -n "^pub enum\|^enum" -A 12 src/lib.rs
Seeing the full enum confirms which variants are missing from the match.
Likely contributors, in order of frequency:
- A new enum variant was added and the existing match was not updated
- A wildcard arm was removed, exposing uncovered variants
- Matching on a reference destructures differently than expected
Root Cause
Rust requires a match to handle every possible value of the scrutinee type. Adding a variant to an enum makes previously exhaustive matches non-exhaustive, which the compiler reports as E0004 with the missing patterns.
The Fix
Add an arm for each missing variant, or add a deliberate wildcard _ => when the default behavior is truly correct; prefer explicit arms so future variants are caught at compile time.
Watch out: A catch-all wildcard silently absorbs new variants, defeating the safety the enum was meant to give.
enum State { Init, Running, Done }
fn label(s: &State) -> &'static str {
match s {
State::Init => "init",
State::Running => "running",
State::Done => "done",
// no wildcard: a new variant becomes a compile error here
}
}
Verify and Prevent
cargo build succeeds and a test constructs each variant and asserts the expected branch is taken.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.