How to Throw Errors in Python

Python uses the raise keyword to “throw” exceptions.

What you’ll build or solve

You’ll raise clear, useful errors in Python so your code fails fast instead of producing confusing results.

When this approach works best

This approach works best when you:

  • Validate user input or function arguments and want to stop early when data is invalid.
  • Guard against impossible states, like negative values that should never happen.
  • Build reusable functions and want callers to see a clear error instead of silent bugs.

Avoid this approach when:

  • “No result” is expected and normal, and returning None (or an empty list) is clearer than raising.

Prerequisites

  • Python 3 installed
  • You know what variables are
  • You can write and call a function

Step-by-step instructions

1) Raise an error with raise

Use raise to stop execution and signal that something is wrong.

age = -3

if age < 0:
    raise ValueError("age must be 0 or higher")

What to look for:

Write a message that clearly states what was expected.


2) Pick a standard exception type

Choose an exception that matches the problem. This makes errors easier to understand and easier to handle later.

Option A (most common): use ValueError for invalid values

def set_discount(percent):
    if percent < 0 or percent > 100:
        raise ValueError("percent must be between 0 and 100")
    return percent

Option B (alternative): use TypeError for invalid types

def repeat(text, times):
    if not isinstance(times, int):
        raise TypeError("times must be an int")
    return text * times

3) Add context to your error message

If the caller passed a bad value, include it in the message.

def get_user(user_id):
    if user_id <= 0:
        raise ValueError(f"user_id must be positive, got {user_id}")
    return {"id": user_id}

What to look for:

Keep the message short, but include the rule and the value.


4) Create your own exception type for a specific domain

Most code should stick to built-in exceptions. In larger projects, a custom exception can make your errors easier to catch and understand.

class PaymentError(Exception):
    pass

def charge(amount):
    if amount <= 0:
        raise PaymentError("amount must be greater than 0")
    return "charged"

Examples you can copy

1) Validate function arguments

def slugify(text):
    if not isinstance(text, str):
        raise TypeError("text must be a string")
    if not text.strip():
        raise ValueError("text must not be empty")
    return text.strip().lower().replace(" ", "-")

2) Guard against missing required keys

This assumes user is a dictionary, like {"email": "a@b.com"}.

def get_email(user):
    if "email" not in user:
        raise KeyError("user must include an 'email' key")
    return user["email"]

3) Stop on an unexpected state

def status_label(status):
    allowed = {"todo", "doing", "done"}
    if status not in allowed:
        raise ValueError(f"status must be one of {sorted(allowed)}, got {status!r}")
    return status.upper()

4) Advanced: re-raise with a clearer message

Use this pattern when you want to convert a low-level error into a more helpful message for your app.

def parse_port(text):
    try:
        port = int(text)
    except ValueError as e:
        raise ValueError(f"port must be an integer, got {text!r}") from e

    if not (1 <= port <= 65535):
        raise ValueError(f"port must be 1..65535, got {port}")

    return port

The from e keeps the original error context in the traceback.


Common mistakes and how to fix them

Mistake 1: Raising a string instead of an exception

You might write:

raise "Bad input"

Why it breaks:

Python requires an exception object, not a plain string.

Correct approach:

raise ValueError("bad input")

Mistake 2: Raising Exception for everything

You might write:

def set_age(age):
    if age < 0:
        raise Exception("bad age")

Why it breaks:

A generic exception type makes the error less clear and harder to handle selectively.

Correct approach:

def set_age(age):
    if age < 0:
        raise ValueError("age must be 0 or higher")
    return age

Mistake 3: Not including a useful message

You might write:

raise ValueError()

Why it breaks:

The traceback shows the exception type but gives no clue what went wrong.

Correct approach:

raise ValueError("expected a number between 1 and 10")

Troubleshooting

If you see TypeError: exceptions must derive from BaseException, you raised something that is not an exception class or instance. Use raise ValueError("..."), not raise "...".

If you see NameError: name 'ValueError' is not defined, a variable named ValueError may be overriding the built-in. Rename your variable and restart Python.

If you see a traceback you do not understand, read the last line first. That line shows the exception type and your message.


Quick recap

  • Python “throws” errors with the raise keyword.
  • Use ValueError for invalid values and TypeError for invalid types.
  • Add a short message that states the rule and, when helpful, the bad value.
  • Use a custom exception only when your project benefits from domain-specific errors.