Rule
Remove unreachable dead code
Unreachable code is confusing,
untestable, and should be removed.
Supported languages: 45+Introduction
Unreachable code signals broken logic in your codebase. Code after return or throw statements was written to execute but never runs. Conditions that are always false hide validation or error handling that never triggers. Branches that logic never reaches due to control flow contain functionality that can't execute. When you find unreachable code, you've found a bug where your code isn't doing what it was intended to do.
Why it matters
Security vulnerabilities: Unreachable security checks don't protect your application. If authentication, authorization, or input validation appears after a return statement, your code looks secure but isn't. Attackers can exploit functions that appear to have security measures but actually bypass them. Code review might miss these vulnerabilities because the security logic exists in the codebase, just never executes.
Logic bugs in production: Dead code means your function isn't implementing the logic you think it is. Validation that never runs lets invalid data through. Error handling that's unreachable means errors propagate uncaught. Business rules that are bypassed produce incorrect results. The code looks correct but behaves differently than intended.Testing gaps: Unreachable code can't be tested. If your test suite passes despite critical code being unreachable, it means you don't have tests covering those paths. Unreachable code reveals gaps in your test coverage where important logic exists but has no tests verifying it runs.
Bundle size impact: Unreachable code still ships to users as dead weight in your JavaScript bundle. Users download and parse code that never runs, but this is secondary to the logic bugs that dead code indicates.
Code examples
❌ Non-compliant:
function transferFunds(fromAccount, toAccount, amount) {
if (!fromAccount || !toAccount) {
return { success: false, error: 'Invalid accounts' };
}
if (amount <= 0) {
return { success: false, error: 'Invalid amount' };
logSuspiciousActivity(fromAccount, amount);
}
const balance = getBalance(fromAccount);
if (balance >= amount) {
deductFunds(fromAccount, amount);
addFunds(toAccount, amount);
return { success: true };
}
return { success: false, error: 'Insufficient funds' };
// Check for fraud patterns
if (isHighRiskTransaction(fromAccount, toAccount, amount)) {
notifyFraudTeam(fromAccount, toAccount, amount);
return { success: false, error: 'Transaction blocked' };
}
}
Why it's wrong: The fraud detection logic never runs because the function returns before reaching it. The suspicious activity logging after the amount check also never executes. This function looks like it has security measures but actually processes all transfers without fraud checks.
✅ Compliant:
function transferFunds(fromAccount, toAccount, amount) {
if (!fromAccount || !toAccount) {
return { success: false, error: 'Invalid accounts' };
}
if (amount <= 0) {
logSuspiciousActivity(fromAccount, amount);
return { success: false, error: 'Invalid amount' };
}
if (isHighRiskTransaction(fromAccount, toAccount, amount)) {
notifyFraudTeam(fromAccount, toAccount, amount);
return { success: false, error: 'Transaction blocked' };
}
const balance = getBalance(fromAccount);
if (balance >= amount) {
deductFunds(fromAccount, amount);
addFunds(toAccount, amount);
return { success: true };
}
return { success: false, error: 'Insufficient funds' };
}
Why this matters: All security checks execute before processing the transfer. Fraud detection runs on every transaction. Suspicious activity gets logged. The function implements the security logic it appears to have.
Conclusion
Unreachable code indicates bugs in your logic where intended functionality never executes. Find it with static analysis tools in your CI pipeline and treat it as a critical issue, not just code cleanup. When you discover unreachable code, investigate why it exists and what logic was supposed to run but doesn't.
.avif)
