PythonMastery
reference 3 min read · lesson 16 of 45 in Errors

ValueError: not enough values to unpack

1 · The lesson

read

What this error means

You asked Python to unpack an iterable into more variables than it actually contained. Unpacking requires an exact match between the number of names on the left and the number of items on the right (unless a starred target is used).

When you see it

python
>>> a, b, c = [1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)

Why it happens

The right-hand side produced fewer items than the left-hand side expected. Common culprits: a split returning fewer parts than expected, a function returning None (which isn't iterable at all — that gives a different error), or a list that has been filtered down to fewer items than your code assumes.

How to fix it

1. Validate the length before unpacking:

python
parts = line.split(",")
if len(parts) == 3:
    name, age, city = parts
else:
    print("malformed line:", line)
+ setup added so this can run · defines line
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

line = _AutoMock('line')

2. Use defaults via slicing or padding:

python
parts = (line.split(",") + ["", "", ""])[:3]
name, age, city = parts
+ setup added so this can run · defines line
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

line = _AutoMock('line')

3. Use dict.get when the shape varies:

python
record = parse(line)               # returns a dict
name = record.get("name", "")
age = record.get("age", 0)
city = record.get("city", "")
+ setup added so this can run · defines parse, line
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

def parse(*_a, **_kw):
    print('-> parse() called')
    return _AutoMock('parse()')
line = _AutoMock('line')

4. Return tuples of consistent length from your functions:

python
def split_name(full):
    parts = full.split(" ", 1)
    if len(parts) == 1:
        return parts[0], ""        # always return two items
    return parts[0], parts[1]

first, last = split_name("Cher")   # works

When you'd actually see this in real code

  • Reading the last line of a file that's just a trailing newline: key, value = line.split("=") raises because the line is empty.
  • Unpacking the result of a regex match.groups() when the pattern didn't match all alternatives and some groups are None — though here you'd typically see a different surface error first.
  • Iterating over enumerate results incorrectly: for i in enumerate(xs): gives a tuple (index, value); writing for i, v, x in enumerate(xs): asks for three values.

See Also

Practice this

on practicepython.in

Short exercises that run in your browser and tell you what your code actually did, not just whether a test passed.