Fix ValueError in Python
Error Reference
ValueError
ValueErrors signal that the type is correct but the actual value is unusable.
Common messages
ValueError: invalid literal for int() with base 10ValueError: could not convert string to floatValueError: not enough values to unpack
The pattern behind all of them: right type, wrong value. int() happily accepts strings — just not every string:
int('42') # 42 — a string, but one that spells an integer
int('abc')
# ValueError: invalid literal for int() with base 10: 'abc'
float('') # empty input field, unfilled form, blank CSV cell...
# ValueError: could not convert string to float: ''
Compare with int([]), which is a TypeError — a list can never become an int, no matter its value. When a ValueError fires, investigate the failing value (the message quotes it) and decide: validate it, default it, or reject it with a clear error.
Unpacking mismatches
Unpacking demands an exact count on both sides, and the messages state the arithmetic:
a, b = [1, 2, 3]
# ValueError: too many values to unpack (expected 2)
a, b, c = [1, 2]
# ValueError: not enough values to unpack (expected 3, got 2)
This often appears when splitting strings that don't have the shape you assumed:
key, value = 'timeout=30'.split('=') # fine
key, value = 'debug'.split('=')
# ValueError: not enough values to unpack (expected 2, got 1)
Fixes: cap the split with split('=', 1) for "everything after the first =", use a starred target like first, *rest = items when the count varies, or check the length before unpacking.
Validate before converting
You might reach for str.isdigit() to pre-check input, but it rejects perfectly convertible strings:
'42'.isdigit() # True
'-3'.isdigit() # False — but int('-3') works
' 42 '.isdigit() # False — but int(' 42 ') == 42 (int strips whitespace)
The pythonic pattern is to just try the conversion and handle the failure — int() already knows every valid spelling, including negatives and surrounding whitespace:
try:
age = int(user_input)
except ValueError as exc:
raise ValueError("Please enter a valid integer age") from exc
Using from exc preserves the original error context in the traceback. In a loop, retry instead of raising:
while True:
try:
age = int(input('Age: '))
break
except ValueError:
print('Not a number, try again.')
Raising ValueError in your own code
Raise it yourself when an argument has the right type but an unusable value — callers get the same error contract the built-ins use:
def set_discount(percent):
if not 0 <= percent <= 100:
raise ValueError(f'percent must be between 0 and 100, got {percent}')
return percent / 100
set_discount(150)
# ValueError: percent must be between 0 and 100, got 150
Put the offending value in the message — future you, reading a log at 2 a.m., will be grateful. Reserve TypeError for wrong types (percent being a string) and ValueError for out-of-range or malformed values.
Frequently Asked Questions
What is the difference between ValueError and TypeError?
TypeError: the type is wrong, so no value of that type could work — int([]) fails for every list. ValueError: the type is fine but this value is not — int('abc') fails only because 'abc' does not spell an integer. Ask: would a different value of the same type succeed? If yes, it's a ValueError.
int([]) # TypeError: int() argument must be a string, a bytes-like object or a real number, not 'list'
int('abc') # ValueError: invalid literal for int() with base 10: 'abc'
How do I safely parse user input into a number?
Wrap the conversion in try/except ValueError instead of pre-checking with isdigit(). isdigit() returns False for negatives ('-3') and padded input (' 42 ') even though int() converts both fine. Trying the conversion is both more correct and simpler — one code path instead of a check that duplicates int()'s rules badly.
def parse_int(text, default=None):
try:
return int(text)
except ValueError:
return default
parse_int(' -3 ') # -3
parse_int('abc') # None