oxc-project/oxc · warning · OxcDiagnostic

Label in break statement is not allowed

Error message

Label in break statement is not allowed

What it means

Diagnostic from oxlint's eslint/no-labels rule (crates/oxc_linter/src/rules/eslint/no_labels.rs:19). It reports 'break someLabel;' where the referenced labeled statement is not exempted by the rule options — the break-with-label form only exists to exit a labeled enclosing statement, so once no-labels bans the label this usage is flagged together with it. Switch statements are exempt only when allowSwitch is set.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_labels.rs:19

use oxc_ast::{
    AstKind,
    ast::{LabelIdentifier, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::Deserialize;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

fn no_labels_diagnostic(message: &'static str, label_span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(message)
        .with_help("Consider refactoring the code to eliminate the need for labels.")
        .with_label(label_span)
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoLabels {
    /// If set to `true`, this rule ignores labels which are sticking to loop statements.
    /// Examples of **correct** code with this option set to `true`:
    /// ```js
    /// label:
    ///     while (true) {
    ///         break label;
    ///     }
    /// ```
    allow_loop: bool,
    /// If set to `true`, this rule ignores labels which are sticking to switch statements.
    /// Examples of **correct** code with this option set to `true`:

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace 'break label;' with a return by extracting the loop nest into a function
  2. Rewrite the exit condition with a boolean flag or restructure the loops so a plain break suffices
  3. Where the pattern is deliberate, enable "allowLoop": true / "allowSwitch": true in the no-labels options

Example fix

// before
outer: for (const row of rows) {
  for (const cell of row) {
    if (cell === null) break outer;
  }
}

// after
function hasNull(rows) {
  for (const row of rows) {
    for (const cell of row) {
      if (cell === null) return true;
    }
  }
  return false;
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: 'break label;' inside nested loops referring to an outer labeled loop (flagged unless the label is on a switch and allowSwitch=true); 'break label;' inside a labeled switch block; any break carrying a label that the options do not permit.

Common situations: Deeply nested loop cleanup code using 'break outer;'; converting an ESLint config that had no-labels enabled and finding old loop-exit code flagged; labels on switch statements used as a goto substitute.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/f51e5eb24f5caa80. Report an issue: GitHub.