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
- Delete or rename the duplicate so each name is declared once per scope.
- Replace the second declaration with a plain assignment (`a = 10` instead of `var a = 10`).
- For intended overloading in TS, use one function with union parameter types, or separate the variants behind `declare function` in a namespace.
- 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
- Run `npx oxlint` in a pre-commit hook (husky/lint-staged) so duplicates never land on main.
- Prefer `const`/`let` over `var` — block-scoped bindings make accidental redeclaration a SyntaxError instead of a lint hit.
- After merge conflicts, grep the resolved file for repeated declaration names before committing.
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
- '{name}' is already declared in the upper scope.
- Unexpected var, use let or const instead.
- '{name}' is already defined as a built-in global variable.
- Variable declarations should be sorted
- All 'var' declarations must be at the top of the function sc
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/ad3808d9a9193d31.
Report an issue: GitHub.