{"record":{"id":"72f69b259be83946","repo":"oxc-project/oxc","slug":"unreachable-code","errorCode":null,"errorMessage":"Unreachable code.","messagePattern":"Unreachable code\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_unreachable.rs","lineNumber":13,"sourceCode":"use oxc_ast::{AstKind, AstType, ast::VariableDeclarationKind};\nuse oxc_cfg::{Instruction, InstructionKind};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::NodeId;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{\n    context::ContextHost, context::LintContext, rule::Rule, utils::effective_unreachable_blocks,\n};\n\nfn no_unreachable_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unreachable code.\")\n        .with_help(\"Remove the unreachable code or fix the control flow to make it reachable.\")\n        .with_label(span)\n}\n\n/// <https://github.com/eslint/eslint/blob/069aa680c78b8516b9a1b568519f1d01e74fb2a2/lib/rules/no-unreachable.js#L196>\n#[derive(Debug, Default, Clone)]\npub struct NoUnreachable;\n\nconst NEEDED_NODE_TYPES: &AstTypesBitset = &AstTypesBitset::from_types(&[\n    AstType::ReturnStatement,\n    AstType::ThrowStatement,\n    AstType::BreakStatement,\n    AstType::ContinueStatement,\n    AstType::WhileStatement,\n    AstType::DoWhileStatement,\n    AstType::ForStatement,\n]);\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_unreachable.rs#L1-L31","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfunction f(x) {\n  return x * 2;\n  console.log('never runs');\n}\n// after\nfunction f(x) {\n  return x * 2;\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["eslint","oxlint","control-flow","dead-code"],"backgroundTag":"unreachable-code","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}