oxc-project/oxc · warning · OxcDiagnostic
Unreachable code.
Error message
Unreachable code.
What it means
Diagnostic from oxlint's no-unreachable rule (port of ESLint no-unreachable). It fires when statements follow a statement that unconditionally terminates control flow (return, throw, break, continue) because the control-flow-graph helper effective_unreachable_blocks proves those statements can never execute.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_unreachable.rs:13
use oxc_ast::{AstKind, AstType, ast::VariableDeclarationKind};
use oxc_cfg::{Instruction, InstructionKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::{GetSpan, Span};
use crate::{
context::ContextHost, context::LintContext, rule::Rule, utils::effective_unreachable_blocks,
};
fn no_unreachable_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unreachable code.")
.with_help("Remove the unreachable code or fix the control flow to make it reachable.")
.with_label(span)
}
/// <https://github.com/eslint/eslint/blob/069aa680c78b8516b9a1b568519f1d01e74fb2a2/lib/rules/no-unreachable.js#L196>
#[derive(Debug, Default, Clone)]
pub struct NoUnreachable;
const NEEDED_NODE_TYPES: &AstTypesBitset = &AstTypesBitset::from_types(&[
AstType::ReturnStatement,
AstType::ThrowStatement,
AstType::BreakStatement,
AstType::ContinueStatement,
AstType::WhileStatement,
AstType::DoWhileStatement,
AstType::ForStatement,
]);
View on GitHub (pinned to e1e7af627c)
Solutions
- Delete the unreachable statements after the terminating statement.
- If the code must run, move it above the return/throw/break/continue.
- If the terminator was meant to be conditional, fix the control flow so the following code is reachable.
- If the dead code is kept intentionally, annotate that line with an oxlint-disable no-unreachable comment.
Example fix
// before
function f(x) {
return x * 2;
console.log('never runs');
}
// after
function f(x) {
return x * 2;
} Defensive patterns
Strategy: validation
Prevention
- Run oxlint in CI (oxlint --deny-warnings) so unreachable code fails before merge.
- Use the editor oxlint integration to surface unreachable code as you type.
- Prefer guard clauses with the happy path last instead of appending code after returns.
- Delete debug statements during cleanup rather than parking them below a terminator.
When it happens
Trigger: Any statement placed after an unconditional return/throw/break/continue in the same block; code after an infinite loop (while(true){} with no break) or after a call that never returns. The rule registers on Return/Throw/Break/ContinueStatement kinds and checks CFG reachability.
Common situations: Guard clauses added during refactoring leave old code below an early return; statements appended after a throw new Error(...); leftover debug code after return; auto-merged branches placing code after a terminator.
Related errors
- Invalid loop. Its body allows only one iteration.
- Lacked a call of `super()` in some code paths.
- Redundant Boolean call
- This label '{label_name}' is unnecessary
- Expected a `break` statement before `case`.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/72f69b259be83946.
Report an issue: GitHub.