{"record":{"id":"2be80db64a679aa0","repo":"oxc-project/oxc","slug":"name-is-already-declared-in-the-upper-scope","errorCode":null,"errorMessage":"'{name}' is already declared in the upper scope.","messagePattern":"'(.+?)' is already declared in the upper scope\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_shadow/mod.rs","lineNumber":37,"sourceCode":"    node::NodeId,\n    symbol::{SymbolFlags, SymbolId},\n};\n\nuse crate::{\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n};\n\npub use options::{HoistOption, NoShadowConfig};\n\npub fn no_shadow_diagnostic(\n    span: Span,\n    name: &str,\n    shadowed_span: Span,\n    is_enum_member: bool,\n) -> OxcDiagnostic {\n    let diagnostic =\n        OxcDiagnostic::warn(format!(\"'{name}' is already declared in the upper scope.\"))\n            .with_help(format!(\n                \"Consider renaming '{name}' to avoid shadowing the variable from the outer scope.\"\n            ))\n            .with_labels([\n                span.label(format!(\"'{name}' is declared here\")),\n                shadowed_span.label(\"shadowed declaration is here\"),\n            ]);\n\n    if is_enum_member {\n        diagnostic.with_note(format!(\n            \"Enum members are added to the enum scope, so references to '{name}' in enum member initializers resolve to this member instead of the declaration in the upper scope.\"\n        ))\n    } else {\n        diagnostic\n    }\n}\n\npub fn no_shadow_global_diagnostic(span: Span, name: &str) -> OxcDiagnostic {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_shadow/mod.rs#L19-L55","documentation":"Diagnostic from oxlint's `no-shadow` rule. It fires when an inner scope declares a binding with the same name as one visible in an outer scope, making the outer binding unreachable inside. Labels point at both declarations; for TypeScript enum members an extra note explains that member initializers resolve inside the enum scope.","triggerScenarios":"`let x = 1; function f() { let x = 2; }`; callback params reusing outer names (`items.map(item => ...)` with an outer `item`); TS `enum E { A = B }` where `B` is an outer binding that members shadow. The `hoist` option (`functions`/`all`/`never`) and `builtinGlobals` tune what counts as shadowed.","commonSituations":"Nested callbacks over similarly-named data; catch blocks declaring `error` when an outer `error` exists; strict codebases enabling no-shadow in pedantic configs after an upgrade.","solutions":["Rename the inner binding to something specific (`userId` instead of `id`).","Rename the outer variable if the inner name is the clearer one.","Adjust `hoist` if function declarations declared after use are being flagged unexpectedly.","Suppress with an `oxlint-ignore no-shadow` comment for intentional shadowing (e.g. minified-style code)."],"exampleFix":"// before\nlet items = [];\nfunction sync() {\n  for (let items of groups) { use(items); }\n}\n\n// after\nlet items = [];\nfunction sync() {\n  for (let group of groups) { use(group); }\n}","handlingStrategy":"validation","validationCode":"// Identify names declared in nested function scopes that match outer declarations\nfunction shadowedNames(src) {\n  const outer = new Set([...src.matchAll(/(?:let|const|var)\\s+([A-Za-z_$][\\w$]*)/g)].map(m => m[1]));\n  const inner = [...src.matchAll(/function\\s*\\w*\\s*\\([^)]*\\)|=>|\\bcatch\\s*\\(/g)];\n  // refine with a real parser for production use; heuristic for quick checks\n  return inner.length && [...outer];\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give loop/callback variables role-specific names (`userId`, not `id`) so they never collide with outer scope.","Rename `catch (error)` bindings that shadow an outer `error`.","Tune `hoist` (`functions`/`all`/`never`) in the rule config so intended patterns are not flagged."],"tags":["lint","eslint","no-shadow","scoping","variables","typescript"],"backgroundTag":"variable-shadowing","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}