ValueError
Raised when an operation receives an argument of the right type but an inappropriate value.
ValueError(message)
Purpose
ValueError signals that a value has the right type but the wrong content for what’s being
asked of it — int("abc") raises it because a string is a perfectly valid argument type for
int() in general, but "abc" specifically doesn’t represent a number.
Example
int("abc") # ValueError: invalid literal for int() with base 10: 'abc'
[1, 2, 3].index(99) # ValueError: 99 is not in list
def set_age(age: int) -> None:
if age < 0:
raise ValueError(f"age cannot be negative, got {age}")
Behavior notes
- Contrast with
TypeError, which signals the argument’s type itself was wrong (int(None), passing alistwhere a function expects astr).ValueErrormeans the type was fine but the specific value wasn’t acceptable. - Raising
ValueErrorwith a specific, descriptive message (asset_agedoes above) is the standard way to reject an invalid argument in your own functions — it’s a real validation tool, not just something the standard library raises at you. - A caller that wants to handle an invalid value gracefully catches
ValueErrorspecifically (except ValueError:), rather than a bareexcept:that would also swallow unrelated bugs.
Common mistakes
- Raising a bare
Exception(or returningNone, or printing an error and continuing) instead of a specific, catchable exception type likeValueError— it works, in the sense that the program doesn’t crash, but it makes deliberate error handling by a caller much harder. - Catching
ValueErrorfar too broadly — around a large block of code instead of just the one call that might raise it — which can mask aValueErrorcoming from somewhere unexpected as if it were the one being handled.
Implementation notes
ValueError and its distinction from TypeError are part of the standard library’s exception
hierarchy — defined by the language, identical across conforming implementations.