oxc-project/oxc · warning · OxcDiagnostic

Labeled statement is not allowed

Error message

Labeled 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). With the rule enabled, it reports any labeled statement that the current options do not exempt: by default all labels are disallowed; with allowLoop=true only labels attached to loop statements are ignored, and with allowSwitch=true labels on switch statements are ignored. Labels are a rarely used, error-prone control-flow feature that most style guides ban.

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. Remove the label and restructure: move the labeled loop into a function and use return instead of break label
  2. If the label only breaks out of nested loops, use a flag variable or Array.prototype.some/every as an alternative
  3. If loop labels are intentionally used, set "allowLoop": true (and "allowSwitch": true where needed) in the no-labels options in .oxlintrc.json

Example fix

// before
outer:
  while (true) {
    for (const x of xs) {
      if (bad(x)) break outer;
    }
  }

// after
function process(xs) {
  while (true) {
    for (const x of xs) {
      if (bad(x)) return;
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// CI guard: reject any labeled statement before it lands
import { execSync } from 'node:child_process';
try {
  execSync('npx oxlint --deny-labels src/ 2>/dev/null || grep -rnE "^\\s*[A-Za-z_$][\\w$]*\\s*:\\s*(while|for|switch|\\{)" src/', { stdio: 'pipe' });
  process.exitCode = 1;
} catch {
  /* clean */
}

Prevention

When it happens

Trigger: Any 'name:' prefix on a statement: 'label: while (true) {...}' (allowed only if allowLoop is true), 'label: switch (a) {...}' (allowed only if allowSwitch is true), and always for 'label: { ... }' or 'label: if (a) {...}'.

Common situations: Enabling the rule as part of migrating an ESLint config (e.g. airbnb-style or strict presets) to oxlint; legacy code using outer-loop labels; generated or ported code from languages where labels are idiomatic.

Related errors


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