← Debugging Guides

阅读中文版本

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.

intermediatedebuggingrustmatchexhaustiveness

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

Interpretation

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.