biome complexity/noUselessLabel
labelled safe
Analysis Nemotron 3 Super
The rule flags labeled statements where the label is never referenced by any break or continue statement within its body.
Fix: Remove the label and colon prefix from the labeled statement, leaving only the underlying statement unchanged.
10 hazards
- Removing a label that is referenced by a break or continue outside the labeled statement’s body changes control flow because the reference becomes unresolved.
- If the labeled statement is a function declaration, removing the label turns it into an expression or alters hoisting behavior.
- When the labeled statement is a block containing a `with` statement, label removal may affect identifier resolution inside `with`.
- If the label shares a name with a variable in an outer scope, removing it could cause a break/continue to incorrectly bind to that variable via label shadowing rules.
- In strict mode, a labeled function declaration has different semantics than an expression; dropping the label may violate early error rules.
- If the label is used as a target for `goto`-like simulation via exceptions, removing it breaks the simulation.
- Comments attached to the label token (e.g., `// label`) may be lost during rewriting if the tool discards leading/trailing tokens on the label.
- When the labeled statement is the sole element of a comma expression, removing the label alters parsing precedence.
- If the label precedes an empty statement (`label: ;`), removing it may trigger ASI issues in subsequent lines.
- In module code, a labeled statement that exports a binding via label reference (uncommon but possible via eval) would lose that binding after removal.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fix ok | Arguments Object & Default Parameters | arguments object, function.length, default parameters, rest parameters |
| r1-p002 | silent prediction off | Variable Shadowing Hazard | If the label shares a name with a variable in an outer scope, removing it could cause a break/continue to incorrectly bind to that variable via label shadowing rules. |
| r1-p003 | silent | __proto__ and Prototype Access | __proto__ keys, prototype access, Object.assign vs spread |
| r1-p004 | fix ok | Async/Await and Generators | async/await ordering, generators and yield position |
| r1-p005 | fix ok | Var Hoisting and Re-declaration | var hoisting and re-declaration inside loops or after use |
| r1-p006 | silent prediction off | Empty Statement and ASI | If the label precedes an empty statement (`label: ;`), removing it may trigger ASI issues in subsequent lines. |
| r1-p007 | silent prediction off | Exception-based Goto Simulation | If the label is used as a target for `goto`-like simulation via exceptions, removing it breaks the simulation. |
| r1-p008 | silent prediction off | Module Export via Label Reference (eval) | In module code, a labeled statement that exports a binding via label reference (uncommon but possible via eval) would lose that binding after removal. |
| r2-p001 | fix ok | Var hoisting and re-declaration | Removing a label can interfere with var hoisting and re-declaration when combined with block-scoped declarations in loops. |
| r2-p002 | silent prediction off | Comments attached to label token | When a comment is attached to the label token (e.g., `label: // comment`), Biome's fix may discard the label and its attached comment, altering source structure even if behavior seems preserved. |
| r2-p003 | silent prediction off | ASI and semicolon-less code | Removing a label before an expression that starts with '(' or '[' can trigger ASI misinterpretation, turning what was a labeled statement into a function call or array indexing. |
| r2-p004 | silent prediction off | Null/undefined distinction and optional chaining | If the labeled statement is part of an optional chain or nullish coalescing expression, removing the label changes precedence and evaluation order, potentially altering short-circuit behavior. |
| r2-p005 | invalid | Strict mode labeled function declaration | In strict mode, a labeled function declaration is invalid (early error). However, some tools may incorrectly treat it as valid during analysis. Removing the label could turn it into a valid function e |
| r2-p006 | silent prediction off | Module export via label reference (eval) | In module code, a labeled statement might be referenced via eval to indirectly export a binding. Removing the label breaks this reference, causing eval to fail to find the label in the lexical environ |
| r2-p007 | invalid | Labeled function declaration hoisting | A labeled function declaration is hoisted as a function, but removing the label turns it into a function expression, which is not hoisted, breaking forward references. |
| r2-p008 | invalid | Temporal Dead Zone after hoisting/reordering | If a labeled statement is involved in a TDZ-prone declaration (like let/const), removing the label and altering statement structure can affect the timing of initialization relative to reference, trigg |
Sources
r1-p001 · Arguments Object & Default Parameters
1function f(a = 1, ...args) {
2 lbl: for (let i = 0; i < args.length; i++) {
3 console.log('arg:', args[i], 'length:', arguments.length);
4 if (i === 0) break lbl;
5 }
6}
7f(5, 6, 7);
--- orig.js 2026-10-17 16:06:41.769995185 -0400 +++ fixed.js 2026-10-17 16:06:42.055981493 -0400 @@ -1,7 +1,7 @@ function f(a = 1, ...args) { lbl: for (let i = 0; i < args.length; i++) { console.log('arg:', args[i], 'length:', arguments.length); - if (i === 0) break lbl; + if (i === 0) break; } } f(5, 6, 7);
arg: 6 length: 3
r1-p002 · Variable Shadowing Hazard
1let lbl = 99;
2{
3 lbl: {
4 console.log('lbl var:', lbl);
5 break lbl;
6 }
7}
8console.log('after:', lbl);
lbl var: 99 after: 99
r1-p003 · __proto__ and Prototype Access
1const obj = { __proto__: { toString: () => 'proto' }, toString: () => 'obj' };
2lbl: {
3 console.log(obj.toString());
4 break lbl;
5}
6console.log(Object.assign({}, obj).toString());
obj obj
r1-p004 · Async/Await and Generators
1async function* gen() {
2 lbl: while (true) {
3 const v = await Promise.resolve(1);
4 console.log('yield:', v);
5 if (v === 1) break lbl;
6 }
7}
8(async () => {
9 for await (const x of gen()) {
10 console.log('got:', x);
11 break;
12 }
13})();
--- orig.js 2026-10-17 16:06:42.690951146 -0400 +++ fixed.js 2026-10-17 16:06:42.956938434 -0400 @@ -2,7 +2,7 @@ lbl: while (true) { const v = await Promise.resolve(1); console.log('yield:', v); - if (v === 1) break lbl; + if (v === 1) break; } } (async () => {
yield: 1
r1-p005 · Var Hoisting and Re-declaration
1function test() {
2 lbl: for (var i = 0; i < 2; i++) {
3 console.log('i:', i);
4 if (i === 0) break lbl;
5 }
6 var i = 99;
7 console.log('after loop i:', i);
8}
9test();
--- orig.js 2026-10-17 16:06:43.128930227 -0400 +++ fixed.js 2026-10-17 16:06:43.393917589 -0400 @@ -1,7 +1,7 @@ function test() { lbl: for (var i = 0; i < 2; i++) { console.log('i:', i); - if (i === 0) break lbl; + if (i === 0) break; } var i = 99; console.log('after loop i:', i);
i: 0 after loop i: 99
r1-p006 · Empty Statement and ASI
1lbl:
2;
3console.log('after semi');
4let x = 1
5console.log('x:', x);
after semi x: 1
r1-p007 · Exception-based Goto Simulation
1try {
2 outer: {
3 try {
4 throw new Error('break outer');
5 } catch (e) {
6 if (e.message === 'break outer') break outer;
7 throw e;
8 }
9 console.log('not reached');
10 }
11} catch (e) {
12 console.log('caught:', e.message);
13}
14console.log('done');
done
r1-p008 · Module Export via Label Reference (eval)
1let exportedValue = 42;
2outer: {
3 eval('exportedValue = 99;');
4 break outer;
5}
6console.log('exportedValue:', exportedValue);
exportedValue: 99
r2-p001 · Var hoisting and re-declaration
1function test() {
2 let result = [];
3 label: for (let i = 0; i < 2; i++) {
4 var x = i + 1;
5 result.push(typeof x, x);
6 if (i === 0) {
7 var x = 99; // re-declaration in same function scope
8 }
9 break label;
10 }
11 console.log(result.join(' '));
12}
13test();
--- orig.js 2026-10-17 16:06:49.333636011 -0400 +++ fixed.js 2026-10-17 16:06:49.599623486 -0400 @@ -6,7 +6,7 @@ if (i === 0) { var x = 99; // re-declaration in same function scope } - break label; + break; } console.log(result.join(' ')); }
number 1
r2-p002 · Comments attached to label token
1function test() {
2 let log = '';
3 outer: // this comment is attached to the label token
4 { log += 'outer';
5 if (true) break outer;
6 }
7 console.log(log);
8}
9test();
outer
r2-p003 · ASI and semicolon-less code
1let x = 42;
2label
3(function() { return x++; })()
4console.log(x);
r2-p004 · Null/undefined distinction and optional chaining
1let obj = { prop: { value: 5 } };
2let result;
3label: if ((obj?.prop ?? {value: 0}).value > 0) {
4 result = obj.prop.value;
5 break label;
6} else {
7 result = -1;
8}
9console.log(result);
5
r2-p005 · Strict mode labeled function declaration (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-06-3)
1"use strict";
2try {
3 label: function f() { return 1; };
4 console.log(typeof f);
5} catch (e) {
6 console.log(e.name, e.message);
7}
r2-p006 · Module export via label reference (eval)
1let exportedValue = 99;
2label: { /* dummy label */ }
3try {
4 eval('console.log(label)'); // attempts to reference label
5} catch (e) {
6 console.log(e.name);
7}
8console.log(exportedValue);
ReferenceError 99
r2-p007 · Labeled function declaration hoisting (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-06-3)
1console.log(typeof f); // should be 'function' if hoisted
2label: function f() { return 42; }
3console.log(f());
r2-p008 · Temporal Dead Zone after hoisting/reordering (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-06-3)
1function test() {
2 console.log(typeof x); // TDZ if not initialized
3 label: let x = 1;
4 console.log(x);
5}
6test();