fixhunt

biome style/noUselessElse

labelled safe
Runs / 2026-10-17T19-38-04-597Z-7kql-biome-style_noUselessElsebiome 2.5.152026-10-17 19:38 UTC8 programs × 2 round(s)16 programs, 7 fired, 7 fixed, 0 findings, 3 rejectedmodel cost $0.0031

Analysis Nemotron 3 Super

Flags redundant else blocks after if statements containing breaking statements (return, break, continue, throw).

Fix: Removes the else block and places its statements directly after the if block, preserving their original order and indentation relative to the enclosing scope.

10 hazards
  • Moving statements from an else block after a continue in a loop changes which iteration they execute in, altering loop behavior.
  • If the else block contains a labeled break, moving it outside may break to a different label or become invalid.
  • Statements with side effects in the else block may now execute regardless of the if condition, changing program state.
  • If the else block declares a variable with let/const, moving it may alter its scope and cause temporal dead zone errors.
  • Comments attached to the else block may be lost or misplaced during the rewrite, affecting readability.
  • If the if block contains a return with a value, moving else statements after it creates unreachable code, potentially hiding logic errors.
  • In a switch case, moving else statements after a return may fall through to the next case if break is missing.
  • If the else block contains a throw, moving it after the if block may change the stack trace or exception handling context.
  • When the if block is inside a try block, moving else statements after it may place them outside the try's scope, altering finally execution.
  • If the else block contains a debugger statement, its execution context may change, affecting debugging behavior.

Programs

idresulttitlehazard
r1-p001fix okHazard 1: Side effects in else block executed unconditionallyStatements with side effects in the else block may now execute regardless of the if condition, changing program state.
r1-p002fix okHazard 2: Temporal dead zone from moved let/constIf the else block declares a variable with let/const, moving it may alter its scope and cause temporal dead zone errors.
r1-p003fix okHazard 3: Changed stack trace from moved throwIf the else block contains a throw, moving it after the if block may change the stack trace or exception handling context.
r1-p004invalidHazard 4: Regex lastIndex interference from unconditional executionregular expressions: escapes, unicode flag, lastIndex with the g flag
r1-p005fix okHazard 5: Debugger statement execution context changedIf the else block contains a debugger statement, its execution context may change, affecting debugging behavior.
r1-p006invalidHazard 6: Else block moved outside try, finally not runWhen the if block is inside a try block, moving else statements after it may place them outside the try's scope, altering finally execution.
r1-p007fix okHazard 7: Labeled break becomes invalid after moveIf the else block contains a labeled break, moving it outside may break to a different label or become invalid.
r1-p008fix okHazard 8: Var hoisting and re-declaration in loopvar hoisting and re-declaration inside loops or after use
r2-p001silent prediction offASI and semicolon-less code causing expression misinterpretationASI and semicolon-less code, leading ( or [ on the next line
r2-p002silent prediction offSide effects in else block now execute unconditionally due to missing guardStatements with side effects in the else block may now execute regardless of the if condition, changing program state.
r2-p003silent prediction offStrict mode violation from misplaced this assignmentstrict vs sloppy mode semantics
r2-p004silent prediction offBlock-scoped function declaration hoisted incorrectly across if/elsefunction declarations inside blocks, switch cases, labeled statements
r2-p005fix okVar re-declaration in loop breaks due to moved else block creating duplicate declarationvar hoisting and re-declaration inside loops or after use
r2-p006invalidFinally block skipped because else moved outside try after return in ifWhen the if block is inside a try block, moving else statements after it may place them outside the try's scope, altering finally execution.
r2-p007silent prediction offComments on else block lost during rewrite reducing code clarityComments attached to the else block may be lost or misplaced during the rewrite, affecting readability.
r2-p008silent prediction offThis binding broken when method extracted from object and else block movedthis binding: arrow vs function, methods extracted from objects, call/apply/bind

Sources

r1-p001 · Hazard 1: Side effects in else block executed unconditionally
1let x = 0;
2function f() {
3 if (false) { return; }
4 else { x += 1; }
5}
6f();
7console.log(x);
--- orig.js	2026-10-17 15:38:13.067702588 -0400
+++ fixed.js	2026-10-17 15:38:13.341699522 -0400
@@ -1,7 +1,7 @@
 let x = 0;
 function f() {
   if (false) { return; }
-  else { x += 1; }
+  x += 1; 
 }
 f();
 console.log(x);
1
r1-p002 · Hazard 2: Temporal dead zone from moved let/const
1function f() {
2 if (true) { return; }
3 else { let x = 1; console.log(x); }
4}
5try { f(); } catch (e) { console.log(e.name + ': ' + e.message); }
--- orig.js	2026-10-17 15:38:13.506697675 -0400
+++ fixed.js	2026-10-17 15:38:13.743695023 -0400
@@ -1,5 +1,5 @@
 function f() {
   if (true) { return; }
-  else { let x = 1; console.log(x); }
+  let x = 1; console.log(x); 
 }
 try { f(); } catch (e) { console.log(e.name + ': ' + e.message); }
r1-p003 · Hazard 3: Changed stack trace from moved throw
1function inner() {
2 if (false) { return; }
3 else { throw new Error('test'); }
4}
5function outer() {
6 try { inner(); } catch (e) { console.log(e.stack.split('\n')[0]); }
7}
8outer();
--- orig.js	2026-10-17 15:38:13.894693333 -0400
+++ fixed.js	2026-10-17 15:38:14.208689807 -0400
@@ -1,6 +1,6 @@
 function inner() {
   if (false) { return; }
-  else { throw new Error('test'); }
+  throw new Error('test'); 
 }
 function outer() {
   try { inner(); } catch (e) { console.log(e.stack.split('\n')[0]); }
Error: test
r1-p004 · Hazard 4: Regex lastIndex interference from unconditional execution (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T19-38-0)
1let regex = /a/g;
2let str = 'aa';
3if (false) { return; }
4else { regex.exec(str); }
5console.log(regex.lastIndex);
r1-p005 · Hazard 5: Debugger statement execution context changed
1function f() {
2 if (true) { return; }
3 else { debugger; console.log('reached'); }
4}
5f();
6console.log('done');
--- orig.js	2026-10-17 15:38:14.419687432 -0400
+++ fixed.js	2026-10-17 15:38:14.688684406 -0400
@@ -1,6 +1,6 @@
 function f() {
   if (true) { return; }
-  else { debugger; console.log('reached'); }
+  debugger; console.log('reached'); 
 }
 f();
 console.log('done');
done
r1-p006 · Hazard 6: Else block moved outside try, finally not run (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T19-38-0)
1let finallyRan = false;
2function f() {
3 try {
4 if (false) { return; }
5 } finally {
6 finallyRan = true;
7 }
8 else { console.log('else'); }
9}
10f();
11console.log(finallyRan);
r1-p007 · Hazard 7: Labeled break becomes invalid after move
1outer: {
2 if (false) { break outer; }
3 else { break outer; }
4}
5console.log('reached');
--- orig.js	2026-10-17 15:38:14.902681998 -0400
+++ fixed.js	2026-10-17 15:38:15.169678984 -0400
@@ -1,5 +1,5 @@
 outer: {
   if (false) { break outer; }
-  else { break outer; }
+  break outer; 
 }
 console.log('reached');
reached
r1-p008 · Hazard 8: Var hoisting and re-declaration in loop
1for (let i = 0; i < 2; i++) {
2 if (false) { continue; }
3 else { var x = i; }
4}
5console.log(x);
--- orig.js	2026-10-17 15:38:15.329677175 -0400
+++ fixed.js	2026-10-17 15:38:15.602674087 -0400
@@ -1,5 +1,5 @@
 for (let i = 0; i < 2; i++) {
   if (false) { continue; }
-  else { var x = i; }
+  var x = i; 
 }
 console.log(x);
1
r2-p001 · ASI and semicolon-less code causing expression misinterpretation
1function f() {
2 if (true)
3 return
4 []
5 console.log('unreachable')
6}
7f()
r2-p002 · Side effects in else block now execute unconditionally due to missing guard
1let x = 0;
2function f(flag) {
3 if (flag) return;
4 x += 1;
5}
6f(true);
7f(false);
8f(false);
9console.log(x);
2
r2-p003 · Strict mode violation from misplaced this assignment
1"use strict";
2let obj = { value: 42 };
3function getValue() {
4 if (this === obj) return this.value;
5 this.value = 99; // should error in strict
6 return -1;
7}
8try {
9 console.log(getValue.call(obj));
10 console.log(getValue());
11} catch (e) {
12 console.log(e.name + ': ' + e.message);
13}
42
TypeError: Cannot set properties of undefined (setting 'value')
r2-p004 · Block-scoped function declaration hoisted incorrectly across if/else
1function test() {
2 if (false) {
3 function f() { return 1; }
4 } else {
5 function f() { return 2; }
6 return f();
7 }
8}
9console.log(test());
2
r2-p005 · Var re-declaration in loop breaks due to moved else block creating duplicate declaration
1for (let i = 0; i < 2; i++) {
2 if (i === 0) continue;
3 var x = 10;
4 console.log(x);
5}
6// After fix: var x hoisted and re-declared each loop -> still works but let's make it fail
7// Let's force error by using same var in else that gets moved
8let result = [];
9for (let i = 0; i < 2; i++) {
10 if (i === 0) continue;
11 else {
12 var x = i + 1;
13 result.push(x);
14 }
15}
16console.log(result.join(','));
--- orig.js	2026-10-17 15:38:22.431595431 -0400
+++ fixed.js	2026-10-17 15:38:22.696592325 -0400
@@ -8,9 +8,8 @@
 let result = [];
 for (let i = 0; i < 2; i++) {
   if (i === 0) continue;
-  else {
+  
     var x = i + 1;
     result.push(x);
-  }
 }
 console.log(result.join(','));
10
2
r2-p006 · Finally block skipped because else moved outside try after return in if (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T19-38-0)
1let log = '';
2try {
3 if (true) {
4 return;
5 } else {
6 log += 'else'; // moved after try, never runs
7 }
8} finally {
9 log += 'finally';
10}
11console.log(log || 'empty');
r2-p007 · Comments on else block lost during rewrite reducing code clarity
1function f(flag) {
2 if (flag) return;
3 // This comment explains why we decrement
4 counter--;
5}
6let counter = 5;
7f(true);
8f(false);
9console.log(counter);
4
r2-p008 · This binding broken when method extracted from object and else block moved
1const obj = {
2 value: 42,
3 getValue() {
4 if (this === obj) return this.value;
5 this.value = 99;
6 return -1;
7 }
8};
9const fn = obj.getValue;
10console.log(fn()); // should return -1 (global this)
11console.log(fn.call(obj)); // should return 42 then 99 on second call
12console.log(fn.call(obj));