qa

When to Use LogicException vs RuntimeException in PHP

Published on December 28, 2025 Last updated December 28, 2025

Introduction

Ever found yourself debugging a PHP application and unsure whether a LogicException or RuntimeException is the right choice? This quick guide clarifies the distinction. You’ll learn how these exceptions, both part of PHP's exception hierarchy, signal different kinds of problems. Understanding when to throw each—logic errors versus runtime issues—will improve code clarity, maintainability, and help you write more robust applications. Let's dive in!

Understanding PHP SPL Exceptions and Their Purpose

PHP's Standard Library (SPL) provides LogicException and RuntimeException as base classes for custom exceptions, each signifying different error conditions. LogicException is intended for situations representing flaws in the program's logic – errors that should not occur if the code is written correctly. These exceptions indicate a bug that requires code correction.

Conversely, RuntimeException handles errors that can only be detected during program execution. These are issues that arise during runtime and aren't predictable or preventable through static analysis or code design alone. They represent conditions that are possible, albeit undesirable, outcomes of the program's operation.

When creating custom exception classes, such as PageNotFoundException, carefully consider the nature of the error. If the error indicates a fundamental logic error, LogicException is the appropriate base. If it’s a runtime condition, RuntimeException is more suitable.

<?php

// Custom exception class for logic errors in application flow
class LogicException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Custom exception class for runtime errors that are not logic issues
class RuntimeException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Custom exception class for page not found errors
class PageNotFoundException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 404, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Example usage of the custom exceptions
try {
    // Simulate a logic error in application flow
    throw new LogicException("Invalid operation attempted");

} catch (LogicException $e) {
    echo "Caught LogicException: " . $e->getMessage() . "\n";
}

try {
    // Simulate a runtime error that is not a logic issue
    throw new RuntimeException("An unexpected error occurred");

} catch (RuntimeException $e) {
    echo "Caught RuntimeException: " . $e->getMessage() . "\n";
}

try {
    // Simulate a page not found error
    throw new PageNotFoundException("Page not found", 404);

} catch (PageNotFoundException $e) {
    echo "Caught PageNotFoundException: " . $e->getMessage() . "\n";
}
?>

LogicException vs RuntimeException: Use Cases and Examples

The distinction between LogicException and RuntimeException in PHP clarifies the nature of errors encountered during program execution. LogicException signals an irrecoverable flaw in the program's design or logic. These errors represent situations that should never occur if the code is functioning correctly and require a direct fix to the underlying code itself.

Conversely, RuntimeException indicates errors that can only be detected during runtime. These errors are not necessarily due to flawed logic but arise from conditions that are only apparent while the program is running. They represent situations where the program can continue, perhaps with degraded functionality, but the error necessitates attention.

Choosing between the two depends on the error's nature. If an error points to a fundamental design issue that prevents expected behavior, LogicException is appropriate. If the error is contingent on runtime conditions, RuntimeException is the more suitable choice.

<?php

// Define a custom exception class for page not found errors
class PageNotFoundException extends RuntimeException {
    public function __construct($message = "Page not found", $code = 404, Exception $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Function to simulate fetching a page
function fetchPage($pageId) {
    // Simulate a database lookup
    $pages = [
        'home' => 'Welcome to the home page',
        'about' => 'This is the about page'
    ];

    if (!isset($pages[$pageId])) {
        throw new PageNotFoundException("The page with ID '$pageId' does not exist.");
    }

    return $pages[$pageId];
}

// Example usage
try {
    // Attempt to fetch a non-existent page
    echo fetchPage('contact');
} catch (PageNotFoundException $e) {
    // Handle the exception by logging and displaying an error message
    error_log($e->getMessage());
    http_response_code($e->getCode());
    echo "Error: " . $e->getMessage();
}
?>

Choosing the Right Base Class for Custom Exceptions

When designing custom exceptions in PHP, choosing between LogicException and RuntimeException is crucial for proper error handling and debugging. LogicException signals a flaw in the program's design or logic – a situation that should never occur if the code is functioning correctly. These exceptions typically indicate a programming error requiring code modification.

RuntimeException, conversely, represents errors detectable only during program execution. These are situations that could conceivably happen despite correct program logic, often related to external factors or runtime conditions. They represent unexpected circumstances that arise while the application is running.

Therefore, use LogicException for errors that represent bugs in your code that need fixing. Employ RuntimeException for conditions that are valid, albeit unexpected, occurrences during program operation.

<?php

// Custom exception class for logic errors in application flow
class LogicException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Custom exception class for runtime errors that are not logic issues
class RuntimeException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Custom exception class for page not found errors
class PageNotFoundException extends Exception {
    // Constructor to set custom error message
    public function __construct($message, $code = 404, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

// Example usage of the custom exceptions
try {
    // Simulate a logic error in application flow
    throw new LogicException("Invalid operation attempted");

} catch (LogicException $e) {
    echo "Caught LogicException: " . $e->getMessage() . "\n";

} catch (RuntimeException $e) {
    echo "Caught RuntimeException: " . $e->getMessage() . "\n";

} catch (PageNotFoundException $e) {
    echo "Caught PageNotFoundException: " . $e->getMessage() . "\n";
}

// Simulate a runtime error that is not a logic issue
try {
    // Attempt to access an undefined variable
    echo $undefinedVariable;

} catch (RuntimeException $e) {
    echo "Caught RuntimeException: " . $e->getMessage() . "\n";

} catch (LogicException $e) {
    echo "Caught LogicException: " . $e->getMessage() . "\n";

} catch (PageNotFoundException $e) {
    echo "Caught PageNotFoundException: " . $e->getMessage() . "\n";
}

// Simulate a page not found error
try {
    // Attempt to access a non-existent page
    throw new PageNotFoundException("Page not found");

} catch (PageNotFoundException $e) {
    echo "Caught PageNotFoundException: " . $e->getMessage() . "\n";

} catch (RuntimeException $e) {
    echo "Caught RuntimeException: " . $e->getMessage() . "\n";

} catch (LogicException $e) {
    echo "Caught LogicException: " . $e->getMessage() . "\n";
}
?>

Conclusion

In PHP, choosing the correct exception type is crucial for maintainable code. RuntimeException signals problems outside of program logic, like file access failures, while LogicException indicates flaws in the program's design or incorrect assumptions. Selecting the appropriate base class—either extending RuntimeException or LogicException—clearly communicates the nature of the error, aiding debugging and improving code clarity.

LogicException RuntimeException PHP exceptions SPL exception hierarchy exception handling PHP error handling when to use LogicException when to use RuntimeException PHP best practices robust PHP applications

Related Articles