Question

How to Raise Exceptions in Python

pythonexception

Question

How can I manually raise an exception in Python so that it can later be caught by an except block?

Short Answer

By the end of this page, you will understand how to manually raise exceptions in Python using raise, how except catches them, when to use built-in exception types versus custom ones, and the common patterns developers use in real code.

Concept

In Python, exceptions are signals that something went wrong or that execution should stop unless the problem is handled. You raise an exception with the raise keyword.

This matters because programs often need to detect invalid input, impossible states, missing data, or failed operations. Instead of silently continuing with bad data, Python code can raise an exception and let another part of the program handle it with try/except.

Basic idea:

raise ValueError("Invalid age")

When Python sees this, it stops normal execution at that line and looks for a matching except block.

A full example:

try:
    raise ValueError("Invalid age")
except ValueError as e:
    print("Caught:", e)

Exceptions are useful because they:

  • make errors explicit
  • separate normal logic from error-handling logic
  • help you fail early when input or state is wrong
  • let callers decide how to recover

Python includes many built-in exception types such as:

  • ValueError for correct type but bad value
  • TypeError for wrong type
  • KeyError for missing dictionary key
  • IndexError for invalid list index
  • RuntimeError for general runtime problems

You can also define your own custom exceptions when built-in ones are not descriptive enough.

Mental Model

Think of an exception like pulling a fire alarm in a building.

  • Normal code execution is people working normally.
  • raise is pulling the alarm.
  • Python immediately stops the current normal flow.
  • except is the emergency response plan that catches the alarm and decides what to do next.

If no one responds to the alarm, the program stops and shows an error.

So raise does not just create a message. It changes the control flow of your program.

Take Quiz

Syntax and Examples

The core syntax is:

raise ExceptionType("message")

Basic example

age = -5

if age < 0:
    raise ValueError("Age cannot be negative")

Here, ValueError is raised because the value is invalid.

Catching the raised exception

try:
    age = -5

    if age < 0:
        raise ValueError("Age cannot be negative")
except ValueError as error:
    print("Caught error:", error)

Output:

Caught error: Age cannot be negative

Raising a generic exception

raise Exception("Something went wrong")

This works, but in real code it is usually better to use a more specific exception type.

Raising a custom exception

class LoginError(Exception):
    pass

username = ""

if not username:
    raise LoginError("Username is required")

This is useful when your application has a specific kind of error that built-in exceptions do not describe well.

Re-raising the current exception

Inside an except block, you can use bare raise to raise the same exception again:

try:
    number = int("abc")
except ValueError:
    print("Logging the error")
    raise

This lets you log or inspect the error before passing it upward.

Step by Step Execution

Consider this example:

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return a / b

try:
    result = divide(10, 0)
    print(result)
except ZeroDivisionError as error:
    print("Caught:", error)

Step by step:

  1. Python defines the divide function.

  2. Execution enters the try block.

  3. divide(10, 0) is called.

  4. Inside divide, Python checks if b == 0.

  5. Since b is 0, Python executes:

    raise ZeroDivisionError("Cannot divide by zero")
    
  6. The function stops immediately. return a / b is never reached.

  7. Python looks for a matching except block.

  8. It finds except ZeroDivisionError as error:.

  9. The exception object is stored in error.

  10. Python runs:

print("Caught:", error)
  1. The program continues after the try/except block.

Output:

Caught: Cannot divide by zero

The key point is that raise interrupts the current flow immediately.

Real World Use Cases

Manual exceptions appear in many practical situations.

Input validation

def set_age(age):
    if age < 0:
        raise ValueError("Age must be 0 or greater")

Used in forms, APIs, and command-line tools.

Business rules

def withdraw(balance, amount):
    if amount > balance:
        raise ValueError("Insufficient funds")
    return balance - amount

Used in banking, checkout flows, and inventory systems.

Configuration checks

def load_config(config):
    if "database_url" not in config:
        raise KeyError("Missing 'database_url' setting")

Used when applications start and require mandatory settings.

API and data processing safeguards

def parse_status(data):
    if "status" not in data:
        raise KeyError("Response missing 'status'")
    return data["status"]

Used when reading JSON, files, or external service responses.

Authentication and permissions

class PermissionDenied(Exception):
    pass


def delete_user(is_admin):
    if not is_admin:
        raise PermissionDenied("Admin access required")

Used in web apps and internal tools.

Take Quiz

Real Codebase Usage

In real projects, developers use raise as part of clear error-handling design.

Guard clauses

A guard clause checks invalid conditions early and stops immediately.

def calculate_discount(price):
    if price < 0:
        raise ValueError("price cannot be negative")
    return price * 0.9

This keeps the rest of the function simpler.

Validation at boundaries

Developers often raise exceptions when data enters the system.

def create_user(email):
    if "@" not in email:
        raise ValueError("Invalid email address")

This prevents bad data from spreading deeper into the codebase.

Converting low-level errors into domain-specific errors

class ConfigError(Exception):
    pass


def read_port(config):
    try:
        return int(config["port"])
    except KeyError:
        raise ConfigError("Missing port setting")
    except ValueError:
        raise ConfigError("Port must be an integer")

This makes higher-level code easier to understand.

Re-raising after logging

try:
    process_data()
except Exception as error:
    print(f"Processing failed: {error}")
    raise

This preserves the original error while still recording useful information.

Early failure instead of silent bugs

Good code often raises an error rather than returning misleading results.

def get_first(items):
    if not items:
        raise ValueError("items cannot be empty")
    return items[0]

Common Mistakes

1. Raising a string instead of an exception

This is invalid in modern Python.

Broken code:

raise "Something went wrong"

Correct:

raise Exception("Something went wrong")

2. Using overly generic Exception everywhere

This works, but it makes errors harder to handle precisely.

Less helpful:

raise Exception("Bad input")

Better:

raise ValueError("Age must be positive")

3. Catching the wrong exception type

try:
    raise ValueError("Bad value")
except TypeError:
    print("This will not run")

Make sure the except type matches the raised exception or a parent class.

4. Forgetting that raise stops execution immediately

Broken expectation:

def test():
    print("Start")
    raise ValueError("Oops")
    print("End")

print("End") never runs.

5. Using bare except too broadly

try:
    do_work()
except:
    print("Something failed")

This can hide unexpected problems. Prefer specific exceptions:

try:
    do_work()
except ValueError as error:
    print(error)

6. Creating custom exceptions without inheriting from Exception

Broken code:

class MyError:
    pass

Correct:

class MyError(Exception):
    pass

7. Swallowing exceptions silently

try:
    risky_operation()
except ValueError:
    pass

This can make bugs hard to find. Handle the exception meaningfully or re-raise it.

Comparisons

ConceptPurposeExampleWhen to use
raiseManually trigger an exceptionraise ValueError("Bad input")When your code detects an error condition
try/exceptHandle an exceptionexcept ValueError:When you want to recover or report the error
returnSend back a normal resultreturn 42When execution succeeds normally
printDisplay informationprint("error")For messages only, not for stopping execution

raise vs return

def get_user(user_id):
    if user_id < 1:
        raise ValueError("Invalid user id")
    return {"id": user_id}
  • raise signals failure.
  • return provides a normal value.

Built-in exceptions vs custom exceptions

TypeExampleBest for
Built-in exceptionValueError, TypeErrorCommon Python errors
Custom exceptionclass LoginError(Exception): passApp-specific problems

raise Exception(...) vs specific exceptions

OptionProsCons
raise Exception(...)SimpleToo broad
raise ValueError(...)Clear and preciseRequires choosing the right type

In most cases, specific exceptions are better.

Take Quiz

Cheat Sheet

Core syntax

raise ValueError("Invalid value")

Catching it

try:
    raise ValueError("Invalid value")
except ValueError as error:
    print(error)

Custom exception

class MyError(Exception):
    pass

raise MyError("Something specific went wrong")

Re-raise current exception

try:
    do_work()
except Exception:
    raise

Quick rules

  • Use raise to trigger an exception manually.
  • Raise exception objects or exception classes derived from Exception.
  • Prefer specific exceptions like ValueError over generic Exception.
  • raise stops execution immediately.
  • Use try/except to catch exceptions.
  • Use custom exceptions for domain-specific errors.

Common built-in exceptions

  • ValueError - value is wrong
  • TypeError - type is wrong
  • KeyError - dictionary key missing
  • IndexError - sequence index invalid
  • ZeroDivisionError - division by zero
  • RuntimeError - general runtime issue

Pattern to remember

if bad_condition:
    raise SomeException("Helpful message")

FAQ

How do you manually throw an exception in Python?

Use the raise keyword:

raise ValueError("Something is wrong")

Can I catch a manually raised exception with except?

Yes. If the except block matches the exception type, it will catch it.

What exception type should I raise in Python?

Use the most specific built-in exception that matches the problem, such as ValueError or TypeError. Create a custom exception when needed.

Can I raise my own custom exception in Python?

Yes. Define a class that inherits from Exception, then raise it.

What happens after raise is executed?

Normal execution stops immediately, and Python looks for a matching except block.

Is raise Exception(...) okay to use?

Yes, but it is usually better to raise a more specific exception so the error is clearer and easier to handle.

What is the difference between raise and assert?

raise is for explicit error handling in your program. assert is mainly for debugging assumptions and can be disabled in optimized runs.

Can I re-raise an exception after catching it?

Yes. Inside an except block, use bare raise to throw the same exception again.

Take Quiz

Mini Project

Description

Build a small input-validation function for a registration system. The function should check whether a username and age are valid. If the data is invalid, it should raise meaningful exceptions. This demonstrates how to use raise to protect your program from bad input and how to catch those errors cleanly.

Goal

Create a Python function that validates registration data and raises exceptions for invalid values, then handle those exceptions with try/except.

Requirements

  • Create a function that accepts a username and an age.
  • Raise a ValueError if the username is empty.
  • Raise a ValueError if the age is negative.
  • Return a success message when the input is valid.
  • Use a try/except block to catch and print validation errors.
Take Quiz

Keep learning

Related questions

View more