# biome style/noUselessElse: fix changes program behavior

Internal evidence sheet generated by fixhunt. Not an issue text. A human re-verifies, checks the duplicates
below, and writes the upstream report in their own words following the project's AI policy.

- Tool: biome 2.5.15
- Rule: style/noUselessElse (tool labels the fix: safe, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity high. The fix hoists the function declaration out of the else block, changing it from a block-scoped declaration (ES2015+) that only exists when the else runs to a function-scoped declaration that is always created. The original program throws a ReferenceError because f is never declared; after the fix f exists and prints 1. The documentation presents the rewrite as equivalent but does not account for block-scoped function declarations.
- Program: minimized from 6 to 6 lines

## Reproducer

```js
function main() {
  if (false) { return; }
  else { function f() { return 1; } }
  try { console.log(f()); } catch (e) { console.log(e.name); }
}
main();
```

## Commands

```sh
node prog.js
bunx @biomejs/biome lint --only=style/noUselessElse --write prog.js
node prog.js
```

## Observed

```
stdout before:
ReferenceError
stdout after:
1
```

## Diff applied by the fix

```diff
--- orig.js	2026-10-22 13:25:14.403790975 -0400
+++ fixed.js	2026-10-22 13:25:14.564793632 -0400
@@ -1,6 +1,6 @@
 function main() {
   if (false) { return; }
-  else { function f() { return 1; } }
+  function f() { return 1; } 
   try { console.log(f()); } catch (e) { console.log(e.name); }
 }
 main();
```

## Why the rewrite is not equivalent (model draft, verify before use)

The original `else` block defines `f` only when the condition is false—always true here—but its scope is limited to that block due to JavaScript’s lexical scoping rules for function declarations inside blocks. After removing the `else`, `f` becomes globally scoped within `main`, so it exists in the `try` block regardless of the conditional. Originally, although logically reachable, the function declaration was still confined to the `else` block’s scope per ES2015+ semantics, making `f` inaccessible outside it despite the condition being constant-false. The rewrite hoists `f` to the function level, changing its visibility and causing different behavior. This violates semantic preservation because scope, not just execution, determines identifier accessibility. The fix incorrectly assumes dead code removal preserves scope, but block-scoped function declarations are not interchangeable with outer-scope ones even when unreachable.

## Upstream search

Queries: "noUselessElse fix", "style noUselessElse conditional block", "style noUselessElse empty if body", "style noUselessElse function declaration"

- duplicate: https://github.com/biomejs/biome/issues/11937
  same rule noUselessElse hoisting a function declaration out of an else block and colliding with an outer binding
- related: https://github.com/biomejs/biome/issues/3770
  same rule noUselessElse but different construct (break in loop)
- related: https://github.com/biomejs/biome/issues/1191
  same rule noUselessElse but different construct (else-if chain)
- related: https://github.com/biomejs/biome/issues/4354
  same rule noUselessElse but different construct (else-if conditional)

<details><summary>All hits</summary>

- [github, open] 💅 `noUselessElse` safe fix hoists a declaration that collides with an outer binding — https://github.com/biomejs/biome/issues/11937
- [github, open] 💅 `noUnnecessaryConditions`: false positive on an overloaded call with `undefined` as the default argument (Vue `inject`) — https://github.com/biomejs/biome/issues/12040
- [github, open] 💅 `noSkippedTests` conditionally skip fix suggestion — https://github.com/biomejs/biome/issues/9295
- [github, open] Extension chokes on large files — https://github.com/biomejs/biome/issues/3860
- [github, open] 💅 `lint/correctness/noUnusedImports` does not consider uses inside comments that precede non-declaration statements (start/end of file, etc.) — https://github.com/biomejs/biome/issues/8762
- [github, open] 💅 `useSortedClasses` cannot sort TailwindCSS classname corretly — https://github.com/biomejs/biome/issues/6498
- [github, closed] 💅 `useSimplifiedLogicExpression` "safe" fix breaks code — https://github.com/biomejs/biome/issues/11351
- [github, closed] 💅 `useExplicitLengthCheck` false positive and broken fix — https://github.com/biomejs/biome/issues/11558
- [github, closed] 💅 noUselessTernary double space in quick fix — https://github.com/biomejs/biome/issues/11092
- [github, closed] 💅 Corrupted CLI safe fix for `useConsistentArrowReturn` — https://github.com/biomejs/biome/issues/8347
- [tavily] 💅 noUselessElse reports useful else · Issue #3770 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/3770
- [tavily] 💅 `noUselessElse` recommendation is wrong · Issue #1191 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/1191
- [tavily] 🐛 Biome ignoring config? · Issue #6459 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/6459
- [tavily] 🐛 `--write` applies fixes to all rules ignoring `--only` · Issue #3470 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/3470
- [github, closed] 💅 noUselessElse does not respect else if conditional — https://github.com/biomejs/biome/issues/4354
- [github, closed] 🐛 Parser fails with "Expected a compound selector" due to @media query — https://github.com/biomejs/biome/issues/3091
- [tavily] format duplicates HTML comments on format. · Issue #11430 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/11430
- [tavily] 💅 Linter does not understand svelte block bindings. Destructuring makes it fail to parse. · Issue #9540 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/9540
- [github, closed] 💅 False positive by lint/nursery/noUselessUndefined — https://github.com/biomejs/biome/issues/6577
- [tavily] 🐛 Biome LSP is treating typescript files as if they were javascript files · Issue #3839 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/3839
- [github, open] 💅 `noUnnecessaryConditions`: a generic call's explicit type argument is ignored — https://github.com/biomejs/biome/issues/11446
- [github, closed] 💅 New rule for `noDeprecatedImports` not working with declarations — https://github.com/biomejs/biome/issues/7635
- [github, closed] 💅 `useHookAtTopLevel` false positive when used with forwardRef — https://github.com/biomejs/biome/issues/9195
- [github, closed] 💅 noFloatingPromises doesn't respect TypeScript overloads — https://github.com/biomejs/biome/issues/9568
- [github, closed] 💅 `nusery/noShadow` should not flag parameter names of function types — https://github.com/biomejs/biome/issues/9482
- [github, closed] 💅 `lint/correctness/noUnusedVariables` triggering on namespaces used to define component props — https://github.com/biomejs/biome/issues/7664
- [github, closed] 💅 False error (or at least a misleading one) - private class member never used — https://github.com/biomejs/biome/issues/6933
- [github, closed] 💅 Function parameters with spread operator are not correctly checked by `noUnusedFunctionParameters` — https://github.com/biomejs/biome/issues/5941
- [tavily] 💅 lint/nursery/noUselessUndefined fix is unsafe for functions with union return types · Issue #6906 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/6906
- [tavily] 💅 Should allow `void` returns when function return type is `void` · Issue #4173 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/4173
- [tavily] 💅 lint/correctness/noUnusedVariables for `catch` clause should suggest removing variable definition as unsafe fix · Issue #6476 · biomejs/biome · GitHub — https://github.com/biomejs/biome/issues/6476

</details>
