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 theView on GitHub (pinned to a3d33dda7c)
Solutions
- Restore or add the assignment the reads expect: `let total = 0;`.
- If the variable is dead, delete the declaration (and its reads — they are now dead too).
- 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
- Initialize declarations at the point of declaration.
- After deleting an assignment during refactor, delete the declaration too.
- Let TypeScript's 'used before assigned' checks cover typed files.
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
- Redundant Boolean call
- This label '{label_name}' is unnecessary
- Do not throw undefined
- Unexpected use of `undefined`
- Unreachable code.
AI-assisted analysis of oxc-project/oxc@a3d33dda7c (2026-08-20).
Data as JSON: /api/errors/3ede237f515c4a92.
Report an issue: GitHub.