core-quality-unreachable-code
Pack: core-quality Default severity: MAJOR Languages: TypeScript, JavaScript Lifecycle: experimental Confidence: 0.95
What it catches
Statements that follow an unconditional return, throw, break, continue, or process.exit() in the same block. Because the prior statement always leaves the block, the next statement cannot execute.
Why this matters for vibe-coded apps
Pure pivot debris. The developer changed direction (or asked the AI to) and left the old code beneath the new exit. The risk isn't the dead line itself — it's that the AI agent now believes logic exists there. A future fix it suggests may try to "improve" code that never actually runs, or skip a real path because the dead path looks active.
Example — flagged
function fetchUser(id: string): User {
return userRepo.get(id);
logger.info('fetched ' + id); // ← dead, never runs
}function shutdown(): void {
process.exit(0);
cleanup(); // ← dead, process already terminating
}for (const item of items) {
if (item < 0) {
continue;
n -= item; // ← dead, continue already left this iteration
}
}Example — not flagged
function pick(x: number): string {
if (x > 0) return 'positive'; // last statement in the if-block — fine
return 'negative';
}
function withHelper(): void {
return;
function helper() {} // hoisted function declaration — fine
}Suggested fix
Two paths:
- The code is genuinely dead — delete it. The AI immediately stops believing in a phantom path.
- The exit was premature — move it (often into a guard above), or remove it. The trailing code becomes live again.
If the line is intentionally kept for context (e.g. a TODO marker before the return), move it above the terminating statement so it actually executes.
Suppressing
function deliberatelyDead(): void {
return;
// Reason: kept as documentation for a soon-to-be-restored branch.
// codemore-ignore-next-line: core-quality-unreachable-code
doSomething();
}The directive must be on the line immediately before the target. If you put a comment between them, the directive suppresses the comment instead.
Implementation
AST-based. Visits Block nodes, classifies the last terminator (ReturnStatement, ThrowStatement, BreakStatement, ContinueStatement, process.exit() call), flags the FIRST statement that follows. Hoisted function declarations and plain var statements are skipped.
Source: `shared/packs/core-quality/core-quality-unreachable-code.ts` Fixtures: `corpus/rules/core-quality-unreachable-code/`