Skip to content

How to Resolve Python Error "TypeError: exceptions must derive from BaseException"

Learn how to fix the Python TypeError when raising non-exception objects by using built-in exceptions (ValueError, TypeError) or creating custom exception classes that inherit from Exception.

The TypeError: exceptions must derive from BaseException is a fundamental error in Python's exception handling mechanism. It occurs when you use the raise statement with something that is not a valid exception object – specifically, something that doesn't inherit (directly or indirectly) from the built-in BaseException class. Typically, this happens when trying to raise a simple string or another non-exception type.

This guide explains Python's exception hierarchy and shows the correct ways to raise built-in or custom exceptions.

Understanding the Error: Python's Exception Hierarchy

Python has a well-defined hierarchy for exceptions, designed for structured error handling. At the very top of this hierarchy sits the BaseException class. All built-in exceptions, and crucially, all exceptions that are meant to be caught and handled within typical program flow, inherit from this base class.

The raise statement is specifically designed to work with instances of classes that fit into this hierarchy. When you raise something, Python expects it to be an object representing an error condition, derived from BaseException.

The Cause: Raising Non-Exception Objects

This TypeError occurs because the object you provided to the raise statement is not an instance of BaseException or one of its subclasses. The most common mistake is trying to raise a simple string.

user_input = "some text"

try:
    if not user_input.isdigit():
        raise "Input must be numeric!"
except TypeError as e:
    print(e)

try:
    error_code = 404
    raise error_code
except TypeError as e:
    print(f"Error raising int: {e}")

Python provides a rich set of built-in exception classes for common error scenarios (ValueError, TypeError, KeyError, FileNotFoundError, IndexError, etc.). The correct way to raise an error is to create an instance of one of these classes, usually passing an informative message to its constructor.

user_input = "some text"
expected_type = int

if not isinstance(user_input, expected_type):
    error_message = f"Input must be of type {expected_type.__name__}, got {type(user_input).__name__}"
    raise TypeError(error_message) # Raise the TypeError instance

user_age = -5
if user_age < 0:
    raise ValueError("Age can not be negative.")

Output:

ERROR!
Traceback (most recent call last):
  File "<main.py>", line 8, in <module>
TypeError: Input must be of type int, got str
  • You instantiate the exception class (e.g., ValueError(...), TypeError(...)) and raise that instance.
  • Consult the Python documentation for built-in exceptions to choose the most semantically appropriate one for your error condition.

Solution 2: Define and Raise Custom Exceptions

For application-specific errors, it's good practice to define your own exception classes. Custom exceptions must inherit from Exception (which itself inherits from BaseException).

class InvalidUserInputError(Exception):
    """Custom exception for invalid user input scenarios."""
    pass # Basic custom exception needs only 'pass'

user_email = "not-an-email"

if "@" not in user_email:
    raise InvalidUserInputError(f"Invalid email format provided: {user_email}")

class NegativeValueError(Exception):
    def __init__(self, value, message="Value can not be negative"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f"{self.message} (value was: {self.value})"

score = -10
if score < 0:
    raise NegativeValueError(score)

Output

ERROR!
Traceback (most recent call last):
  File "<main.py>", line 12, in <module>
InvalidUserInputError: Invalid email format provided: not-an-email
  • Always inherit from Exception for standard application errors.
  • Custom exceptions make your error handling more specific and readable (e.g., except InvalidUserInputError:).

Important Distinction: BaseException vs. Exception

While the error message mentions BaseException, you should almost always inherit your custom exceptions from Exception, not directly from BaseException.

  • BaseException: The ultimate base class. It includes exceptions that are generally not meant to be caught by typical application code, such as SystemExit (raised by sys.exit()) and KeyboardInterrupt (raised when the user presses Ctrl+C). Catching BaseException can mask these critical exit signals.
  • Exception: Inherits from BaseException. This is the base class for virtually all built-in, non-system-exiting exceptions (ValueError, TypeError, etc.). Your custom exceptions should inherit from Exception so that standard except Exception: blocks can catch them if necessary, while still allowing system exits to propagate.

Handling Raised Exceptions (try...except)

Remember that if an exception is raised and not handled by an appropriate except block, your program will terminate and print a traceback.

def check_value(val):
    if val < 0:
        raise ValueError("Value must be non-negative.")
    return val * 2

try:
    result = check_value(-5) # This will raise ValueError
    print(f"Result: {result}")
except ValueError as e:
    print(f"Caught expected error: {e}") # Output: Value must be non-negative.
except Exception as e:
    print(f"Caught unexpected standard error: {e}")

print("Program continues after handling.")

Output:

ERROR!
Caught expected error: Value must be non-negative.
Program continues after handling.

Handling exceptions allows your program to recover from errors or log them gracefully instead of crashing.

Conclusion

The TypeError: exceptions must derive from BaseException signals that you attempted to raise an object that is not part of Python's exception hierarchy (most often a plain string).

To fix this:

  1. Raise instances of appropriate built-in exception classes (inheriting from Exception, like ValueError, TypeError, RuntimeError, etc.): raise ValueError("An informative message").
  2. Define custom exception classes for application-specific errors, ensuring they inherit from Exception: class MyCustomError(Exception): pass, then raise MyCustomError("Details").

Never raise raw strings, numbers, or other non-exception types. Always use objects instantiated from classes derived from Exception.

Navigation