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
- Replace 'break label;' with a return by extracting the loop nest into a function
- Rewrite the exit condition with a boolean flag or restructure the loops so a plain break suffices
- 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
- Model early exit from nested loops as a function with return
- Use some()/every()/find() instead of break-with-label scans
- If labels must stay, configure allowLoop/allowSwitch explicitly rather than inline disables
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
- Labeled statement is not allowed
- Label in continue statement is not allowed
- Unnecessary `else` after `return`.
- Unexpected empty block statements
- Found identifier '{name}' with the same name as a label.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/f51e5eb24f5caa80.
Report an issue: GitHub.