Weakness reference
CWE-390

Detection of Error Condition Without Action

This weakness occurs when code detects that something has gone wrong—a failed authentication, a missing file, a database connection error—but then does nothing…

01Summary

This weakness occurs when code detects that something has gone wrong—a failed authentication, a missing file, a database connection error—but then does nothing about it. The application continues as if the error never happened, potentially leaving it in an unsafe state or allowing a security failure to go unnoticed. Silent failures are particularly dangerous because they can mask attacks or data corruption that should have been caught and handled.

02How It Happens

Most programming languages provide mechanisms to detect errors: exception handlers, return codes, status flags, or conditional checks. However, detecting an error is only half the job. The code must then decide what to do: log it, alert an administrator, fail safely, retry, or roll back a transaction. When a developer catches or checks for an error but then takes no action—neither handling it nor propagating it—the error is effectively ignored. The application state becomes inconsistent, security checks may be bypassed, or critical operations may appear to succeed when they have actually failed.

This often happens accidentally: a developer adds error detection during debugging, then forgets to implement the response. It can also result from incomplete refactoring, where error handling was removed but the detection code was left behind. In some cases, developers assume an error "can't happen" and leave the handler empty as a placeholder.

03Real-World Impact

Silent error handling can lead to serious security and reliability issues. A failed password verification that is detected but not acted upon could allow unauthorized access. A failed file write might leave the application in an inconsistent state, corrupting data or allowing stale information to be served. A failed cryptographic operation that is silently ignored could result in unencrypted data being transmitted. In all these cases, the application appears to be functioning normally, making the problem difficult to detect until significant damage has occurred.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sqlite3

def update_user_password(user_id, new_password):
    try:
        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()
        cursor.execute(
            "UPDATE users SET password = ? WHERE id = ?",
            (hash_password(new_password), user_id)
        )
        conn.commit()
    except sqlite3.Error:
        pass  # Error detected but ignored
    finally:
        conn.close()
    
    return True  # Always returns success, even if update failed

Why it's vulnerable:
The code catches database errors but takes no action—it doesn't log, re-raise, or return a failure status. The caller believes the password was updated when it may not have been.

Fixed pattern
import sqlite3
import logging

def update_user_password(user_id, new_password):
    try:
        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()
        cursor.execute(
            "UPDATE users SET password = ? WHERE id = ?",
            (hash_password(new_password), user_id)
        )
        conn.commit()
        return True
    except sqlite3.Error as e:
        logging.error(f"Password update failed for user {user_id}: {e}")
        return False
    finally:
        conn.close()
Vulnerable pattern
<?php
function verify_and_log_login($username, $password) {
    $user = get_user_by_username($username);
    
    if (!$user) {
        // Error detected but not handled
    }
    
    if (!password_verify($password, $user['password_hash'])) {
        // Authentication failed but no action taken
    }
    
    $_SESSION['user_id'] = $user['id'];
    return true;
}
?>

Why it's vulnerable:
Failed user lookup and failed password verification are detected but ignored. The session is set regardless, potentially logging in an unauthenticated user or causing a fatal error later.

Fixed pattern
<?php
function verify_and_log_login($username, $password) {
    $user = get_user_by_username($username);
    
    if (!$user) {
        error_log("Login attempt for non-existent user: " . $username);
        return false;
    }
    
    if (!password_verify($password, $user['password_hash'])) {
        error_log("Failed login attempt for user: " . $username);
        return false;
    }
    
    $_SESSION['user_id'] = $user['id'];
    return true;
}
?>

05Prevention Checklist

Never leave exception handlers empty.
Every catch, except, or error check must have a body: log the error, return a failure status, re-raise it, or take corrective action.
Distinguish between recoverable and fatal errors.
Decide in advance which errors should be retried, which should fail gracefully, and which should halt execution.
Log all security-relevant errors.
Failed authentication, authorization checks, and cryptographic operations must be logged for audit and incident response.
Return meaningful status to the caller.
Functions should indicate success or failure clearly—via return codes, exceptions, or out-parameters—so the caller can respond appropriately.
Test error paths explicitly.
Write unit tests that trigger error conditions and verify that the application responds correctly, not silently.
Use static analysis tools.
Linters and SAST tools can flag empty exception handlers or unreachable error-handling code.

06Signs You May Already Be Affected

Review your application logs for patterns: are there operations that should always produce a log entry (login attempts, file writes, API calls) but sometimes don't? Check your codebase for empty catch blocks, except clauses with only pass, or conditional branches that detect errors but contain no statements. If you find these patterns, trace the code path to understand what happens when the error occurs—if the application continues silently, that's a sign this weakness is present.

07Related Recent Vulnerabilities