---
title: Do Not Throw Generic Errors
impact: HIGH
impactDescription: enables proper error handling and monitoring
tags: error-handling, exceptions, custom-errors, debugging, quality, php
---

## Do Not Throw Generic Errors

Throwing generic exceptions like `\Exception`, `\Error`, or `\RuntimeException` with vague messages makes it impossible to distinguish between different types of failure. Proper error handling requires specific exception types that convey meaning and context.

**Incorrect (generic errors):**

```php
if (!$user) {
    throw new \Exception("error"); // Vague message, generic type
}

if ($amount < 0) {
    throw new \RuntimeException("Invalid"); // Generic type
}

// In Laravel - avoid generic aborts without explanation
abort(500); 
```

**Correct (specific exceptions with context):**

```php
if (!$user) {
    throw new UserNotFoundException("User with ID {$userId} not found in database.");
}

if ($amount < 0) {
    throw new InvalidTransactionAmountException("Transaction amount '{$amount}' cannot be negative.");
}

// Custom error with structured context (if supported by your base exception)
throw new ValidationException([
    'email' => 'The provided email is already in use.',
    'code' => 'EMAIL_TAKEN'
]);
```

**Custom errors should include:**
- A descriptive message that explains **what** failed and **why**.
- Relevant identifiers (IDs, keys) for easier debugging.
- Specific exception types that allow for targeted `catch` blocks.

**Tools:** PHPStan, Psalm, PR review
