Skip to content
Latchkey

Rust "unused variable" Denied as Error (-D warnings) in CI

A normally-harmless warning (an unused variable, unused import, or dead code) was promoted to a hard error because the build runs with -D warnings or #![deny(warnings)]. CI fails on the lint that local cargo build would only warn about.

What this error means

CI fails with error: unused variable: x` (note: -D unused-variables ... -D warnings`) even though it builds locally. The same code only warns when you drop the deny flag.

cargo
error: unused variable: `config`
 --> src/main.rs:3:9
  |
3 |     let config = load();
  |         ^^^^^^ help: if this is intentional, prefix it with an underscore: `_config`
  = note: `-D unused-variables` implied by `-D warnings`

Common causes

Warnings denied in CI

A RUSTFLAGS="-D warnings", a -D warnings on the cargo invocation, or #![deny(warnings)] turns every lint into a compile error. The unused variable then fails the build.

Leftover or intentionally-unused bindings

A binding kept for a side effect, a future use, or a destructured value you do not need triggers the lint that the deny promotes to an error.

How to fix it

Fix the lint at the source

  1. Remove the truly unused variable or import.
  2. Prefix an intentionally-unused binding with _ (e.g. _config).
  3. Use let _ = expr; to keep a side effect without binding a name.

Scope an allow if the lint is acceptable

Allow the specific lint narrowly rather than dropping -D warnings globally.

Rust
#[allow(unused_variables)]
fn handler(config: Config) { /* ... */ }

How to prevent it

  • Run cargo clippy -- -D warnings locally to catch denied lints before CI.
  • Prefix deliberately-unused bindings with _.
  • Scope #[allow(...)] narrowly instead of disabling -D warnings.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →