oxc-project/oxc · warning · OxcDiagnostic

'{ident_name}' is always 'undefined' because it's never assi

Error message

'{ident_name}' is always 'undefined' because it's never assigned.

What it means

`no-unassigned-vars` reports `let`/`var` declarations that are never assigned anywhere in the program — the symbol is read but always evaluates to `undefined`. The diagnostic interpolates the identifier name: `'{ident_name}' is always 'undefined' because it's never assigned.` It targets declarations that look like they should carry a value (dead intent) rather than intentional undefined sentinels.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_unassigned_vars.rs:9

use oxc_ast::{AstKind, ast::BindingPattern};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{AstNode, context::LintContext, rule::Rule};

fn no_unassigned_vars_diagnostic(span: Span, ident_name: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!(
        "'{ident_name}' is always 'undefined' because it's never assigned.",
    ))
    .with_help(
        "Variable declared without assignment. Either assign a value or remove the declaration.",
    )
    .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoUnassignedVars;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow let or var variables that are read but never assigned.
    ///
    /// #### Ignored Files
    /// This rule ignores `.svelte` and `.vue` files entirely. Oxlint only parses the

View on GitHub (pinned to a3d33dda7c)

Solutions

  1. Restore or add the assignment the reads expect: `let total = 0;`.
  2. If the variable is dead, delete the declaration (and its reads — they are now dead too).
  3. If undefined-on-purpose is intended, make it explicit and reviewable: `let cached = undefined;` reads as intentional, or restructure to return/param passing.

Example fix

// before
let total;
console.log(`total: ${total}`); // always undefined

// after
let total = 0;
console.log(`total: ${total}`);
Defensive patterns

Strategy: validation

Validate before calling

# find never-assigned declarations textually (heuristic)
rg -n '^\s*(let|var)\s+[A-Za-z_$][\w$]*\s*;' src/

Prevention

When it happens

Trigger: `let total;` followed by reads of `total` but no assignment (`total = ...`) anywhere; declarations left behind after deleting the code that computed them.

Common situations: Deleting an initialization during a refactor and leaving the declaration; copy-paste scaffolding (`let result, data, err;`); migrating from `var` hoisting patterns where values were assigned conditionally and one branch was removed.

Related errors


AI-assisted analysis of oxc-project/oxc@a3d33dda7c (2026-08-20). Data as JSON: /api/errors/3ede237f515c4a92. Report an issue: GitHub.