Python raise Statement
Table of Contents + −
In the last lesson you learned about the finally Block. That block runs cleanup code no matter what happens. So far you have mostly been catching errors that Python throws at you. Now we flip it around. Sometimes you want to throw an error yourself, on purpose. That is what raise is for. When something is wrong with the data coming into your code, you can stop right there and say so clearly.
🤔 Why Raise Your Own Error?
Imagine you write a function that takes a person’s age. Someone calls it with -5. A negative age makes no sense. But Python does not know that. To Python, -5 is a perfectly fine number. So your function happily keeps going with bad data.
Here is the pain. That bad value does not crash anything right away. It quietly travels deeper into your program. Maybe it gets saved to a file. Maybe it goes into a calculation ten functions later. And that is where things finally break. It breaks far from where the real mistake was. Now you are hunting for a bug in the wrong place.
The fix is simple. Stop the moment you notice the problem. raise lets you throw your own error with a clear message right where the bad data shows up. This idea is called “fail fast”. You catch the problem early, while it is still easy to understand and fix.
🧩 What raise Does
raise tells Python to stop normal running and signal that something went wrong. You hand it an exception. An exception is Python’s word for an error object that describes what happened.
Here is the basic shape of it.
raise ExceptionType("a clear message about what went wrong")A few things to notice here:
raiseis the keyword that throws the error.ExceptionTypeis the kind of error, likeValueErrororTypeError. Python has many built-in ones.- The text in quotes is your message. It shows up in the error so whoever reads it knows exactly what was wrong.
When this line runs, the function stops right there. The error travels up until something catches it. If nothing catches it, the error reaches the top and stops the program with a message.
Note
ValueError is the right choice when the type is fine but the value is wrong. A negative age is still a number, so the type is okay. The value just does not make sense. That is a ValueError.
🧑💻 A Real Example: Checking the Input
Let’s build a function that sets a person’s age and refuses bad values. We check the input first. If it is wrong, we raise an error.
def set_age(age): if age < 0: raise ValueError("Age cannot be negative") print("Age set to", age)
set_age(25)set_age(-5)Walk through it line by line.
set_agetakes anagevalue.- The
if age < 0:checks for the bad case first. - If the age is negative,
raise ValueError(...)throws an error and the function stops immediately. - If the age is fine, we skip the
raiseand reach theprint.
When we call set_age(25), the age is fine, so it prints. Then set_age(-5) hits the raise, and Python stops with our message.
Output
Age set to 25Traceback (most recent call last): File "main.py", line 7, in <module> set_age(-5) File "main.py", line 3, in set_age raise ValueError("Age cannot be negative")ValueError: Age cannot be negativeSee the last line? It shows the exact error type and your exact message. Anyone reading this knows right away what went wrong and where. That is so much better than a strange crash ten steps later with a confusing message.
Checking the bad case at the very top of a function like this is a common habit. It is called a guard clause. It guards the rest of the function from running with bad data. The good code below it only runs once the input has passed the check.
🎯 Catching the Error You Raised
An error you raise is a normal exception. So you can catch it with try and except, just like any error Python throws. That means the caller can decide what to do instead of letting the program stop.
Here we call set_age inside a try and handle the problem ourselves.
def set_age(age): if age < 0: raise ValueError("Age cannot be negative") return age
try: set_age(-5)except ValueError as error: print("Could not set age:", error)The function raises the error like before. But this time the call sits inside a try. So the except ValueError catches it. The as error part gives us the exception object, and printing it shows our message.
Output
Could not set age: Age cannot be negativeNotice the program did not crash this time. We raised the error to signal the problem. Then the caller caught it and handled it calmly. This is the real pattern. The function that finds the problem raises. The code that knows how to react catches.
Tip
Raise the error where you notice the problem. Catch it where you know what to do about it. Those are often two different places, and that separation is the whole point.
🪧 A Clear Message Saves You Later
The message you put in raise is not just decoration. It is the note your future self reads when something breaks.
Compare these two. Both stop the program, but only one tells you anything useful.
# ❌ Avoid: no message, you are left guessingraise ValueError
# ✅ Good: says exactly what was wrong and which valueraise ValueError("Age cannot be negative")The first one still works. But when it shows up you only see ValueError with no hint. The second one tells you the rule that was broken. When you read it weeks later, you will be glad you wrote a real sentence.
⚠️ Common Mistakes
A few things trip people up the first time. Watch for these.
- Returning instead of raising for a real error. Returning a value like
-1to mean “something went wrong” is easy to ignore. Araisecannot be missed.
# ❌ Avoid: a quiet -1 that the caller might forget to checkdef set_age(age): if age < 0: return -1
# ✅ Good: a loud, clear stopdef set_age(age): if age < 0: raise ValueError("Age cannot be negative")- Forgetting to actually
raiseit. WritingValueError("Age cannot be negative")on its own just creates the error and throws it away. You must putraisein front.
# ❌ Avoid: creates the error but never raises itValueError("Age cannot be negative")
# ✅ Good: actually raises itraise ValueError("Age cannot be negative")-
Catching the wrong type. If you raise a
ValueErrorbut writeexcept TypeError, your handler never runs and the program still stops. Match the type you catch to the type you raise. -
Using a vague error type when a specific one fits. Reach for
ValueErrorfor a bad value,TypeErrorfor a wrong type. The right type helps the caller catch exactly what they mean to.
✅ Best Practices
Keep these habits and your raise calls stay clear and useful.
- Check bad input at the top of the function with a guard clause, then raise. The rest of the function can trust the data after that.
- Always pass a clear message that names the rule that was broken, like “Age cannot be negative”.
- Pick the most fitting built-in error.
ValueErrorfor a bad value,TypeErrorfor the wrong type. - Raise where you find the problem. Catch where you can actually handle it. Do not catch an error in the same spot just to ignore it.
🧩 What You’ve Learned
✅ raise lets you throw your own exception on purpose, to stop early when something is wrong.
✅ Failing fast means you stop right where the bad data appears, not ten steps later in a confusing place.
✅ raise ValueError("Age cannot be negative") is the pattern for a value that is the wrong kind, with a clear message.
✅ A guard clause at the top of a function checks bad input first and raises before the real work runs.
✅ An error you raise is a normal exception, so the caller can catch it with try and except.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does the raise statement do?
Why: raise lets you throw an exception yourself, stopping normal running to signal that something is wrong.
- 2
Why is it better to raise an error early instead of letting bad data continue?
Why: Failing fast stops at the source of the problem, so you debug where the real mistake is, not somewhere far away.
- 3
Which error type best fits a negative age, where the type is fine but the value is wrong?
Why: The value is a valid number but does not make sense, so ValueError is the right choice.
- 4
What is wrong with the line ValueError("Age cannot be negative") written on its own?
Why: Without the raise keyword in front, you only build the exception object and throw it away; you must write raise to actually throw it.
🚀 What’s Next?
You can now raise Python’s built-in errors with a clear message. Next you will learn how to build your own error types that describe exactly the problems in your program.