oxc-project/oxc · warning · OxcDiagnostic

'{name}' is already defined.

Error message

'{name}' is already defined.

What it means

Diagnostic from oxlint's port of ESLint `no-redeclare`. It fires when the same binding name is declared more than once within one scope. JS only permits this for `var`/`function` (and TS redeclare forms), and it usually means a bug or a merge leftover. The primary label points at the original declaration, the secondary label at the redeclaration.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_redeclare.rs:15

use javascript_globals::GLOBALS_BUILTIN;

use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::Deserialize;

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

fn no_redeclare_diagnostic(name: &str, decl_span: Span, re_decl_span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("'{name}' is already defined."))
        .with_help("Use a different variable name or remove the duplicate declaration.")
        .with_labels([
            decl_span.label(format!("'{name}' is already defined.")),
            re_decl_span.label("It can not be redeclared here."),
        ])
}

fn no_redeclare_as_builtin_in_diagnostic(name: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("'{name}' is already defined as a built-in global variable."))
        .with_help("Use a different variable name to avoid shadowing the built-in global.")
        .with_label(span)
}

#[derive(Debug, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoRedeclare {
    /// When set `true`, it flags redeclaring built-in globals (e.g., `let Object = 1;`).
    builtin_globals: bool,

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Delete or rename the duplicate so each name is declared once per scope.
  2. Replace the second declaration with a plain assignment (`a = 10` instead of `var a = 10`).
  3. For intended overloading in TS, use one function with union parameter types, or separate the variants behind `declare function` in a namespace.
  4. If the duplication is intentional, add an `oxlint-ignore no-redeclare` comment or disable the rule in .oxlintrc.

Example fix

// before
var a = 3;
var a = 10;

// after
var a = 3;
a = 10;
Defensive patterns

Strategy: validation

Validate before calling

// Pre-commit check: catch duplicate var/function names per top-level scope
const { execSync } = require('node:child_process');
const src = require('node:fs').readFileSync(process.argv[2], 'utf8');
const seen = new Set();
for (const m of src.matchAll(/(?:var|let|const|function)\s+([A-Za-z_$][\w$]*)/g)) {
  if (seen.has(m[1])) {
    console.error(`duplicate declaration: ${m[1]}`);
    process.exitCode = 1;
  }
  seen.add(m[1]);
}

Prevention

When it happens

Trigger: `run_once` walks every symbol in the semantic scoping data and reports each adjacent pair in `symbol_redeclarations`: `var a = 1; var a = 2;`, two non-`declare` function declarations of the same name in one scope, `var f; function f(){}`. In TypeScript sources, TS redeclaration entries are compared too (`class C {} var C;`).

Common situations: Copy-paste or git-merge leftovers; migrating loose scripts into a linted repo; TypeScript code that tries to overload functions by declaring them twice instead of using a single signature with union types.

Related errors


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