Fix: Python ValueError: Too Many Values to Unpack
Quick Answer
Learn why Python raises ValueError too many values to unpack and how to fix it when unpacking tuples, iterating dictionaries, parsing files, and using zip or enumerate.
The Error
You run a Python script and get:
Traceback (most recent call last):
File "app.py", line 3, in <module>
a, b = (1, 2, 3)
ValueError: too many values to unpack (expected 2)Or the reverse:
ValueError: not enough values to unpack (expected 3, got 2)Both errors come from the same root cause: a mismatch between the number of variables on the left side of an assignment and the number of values on the right side.
This error shows up in tuple unpacking, dictionary iteration, function return values, file parsing, and several other common patterns. Each scenario has a different fix.
Why This Happens
Python supports unpacking assignment, where you assign multiple variables at once from an iterable:
a, b, c = [1, 2, 3]Python expects the number of variables on the left to match the number of values on the right exactly. When they do not match, you get a ValueError.
The “too many values” variant means the right side has more elements than the left side has variables. The “not enough values” variant means the opposite.
This is strict by design. Python does not silently drop extra values or fill missing ones with None. It forces you to be explicit about how many values you expect, which prevents subtle bugs where data silently goes missing.
The error appears in several common scenarios:
- Unpacking a tuple or list with the wrong number of variables
- Iterating over a dictionary without calling
.items() - Ignoring extra return values from a function
- Parsing CSV rows or file lines with unexpected columns
- Misusing
enumerate()orzip() - Nested unpacking with incorrect structure
Each of these has a specific fix, covered below.
Fix 1: Match the Number of Variables to the Iterable
The simplest case. You have a tuple or list with N elements but only M variables on the left.
Broken:
coordinates = (10, 20, 30)
x, y = coordinates # ValueError: too many values to unpack (expected 2)Fixed:
coordinates = (10, 20, 30)
x, y, z = coordinatesIf you genuinely do not know how many elements the iterable contains, check its length first:
coordinates = (10, 20, 30)
if len(coordinates) == 2:
x, y = coordinates
elif len(coordinates) == 3:
x, y, z = coordinatesOr index directly instead of unpacking:
x = coordinates[0]
y = coordinates[1]Pro Tip: When debugging this error, print the value you are trying to unpack right before the failing line. The mismatch is often caused by unexpected data, not wrong code. A quick
print(len(coordinates), coordinates)reveals the real shape of your data.
Fix 2: Use Star Expressions to Capture Extra Values
Python 3 introduced star expressions (*variable) for unpacking. This lets you capture the “rest” of an iterable into a list without knowing its exact length.
Capture trailing values:
first, *rest = [1, 2, 3, 4, 5]
# first = 1
# rest = [2, 3, 4, 5]Capture leading values:
*rest, last = [1, 2, 3, 4, 5]
# rest = [1, 2, 3, 4]
# last = 5Capture the middle:
first, *middle, last = [1, 2, 3, 4, 5]
# first = 1
# middle = [2, 3, 4]
# last = 5Discard extra values with *_:
If you only need certain values and want to throw away the rest:
name, age, *_ = ("Alice", 30, "Engineer", "NYC", "USA")
# name = "Alice"
# age = 30
# _ = ["Engineer", "NYC", "USA"] (discarded)Star expressions are useful when dealing with data of variable length, such as log lines, CSV rows with optional columns, or API responses that may include extra fields.
You can only use one star expression per unpacking assignment. This raises a SyntaxError:
*a, *b = [1, 2, 3] # SyntaxError: multiple starred expressions in assignmentFix 3: Use .items() When Iterating Dictionaries
A common mistake is trying to unpack both keys and values from a dictionary using a plain for loop.
Broken:
user = {"name": "Alice", "age": 30}
for key, value in user:
print(key, value)
# ValueError: too many values to unpack (expected 2)Wait, this actually raises ValueError: too many values to unpack only in specific cases. Iterating over a plain dictionary yields keys only (strings). If a key has more than two characters, unpacking it into two variables fails because the string has too many characters.
for key, value in user:
# "name" is iterated as 'n', 'a', 'm', 'e' — 4 values, expected 2
passFixed — use .items():
user = {"name": "Alice", "age": 30}
for key, value in user.items():
print(key, value)The .items() method returns (key, value) tuples, which unpack cleanly into two variables.
Similarly, if you only need values, use .values():
for value in user.values():
print(value)This is one of the most common sources of this error for Python beginners. If you see this error inside a for loop with a dictionary, check whether you forgot .items().
For related dictionary errors, see Python KeyError and Python RuntimeError: dictionary changed size during iteration.
Fix 4: Handle Function Return Values Correctly
Functions that return tuples are another frequent source of unpacking errors. The caller must unpack the correct number of values.
Broken:
def get_user_info():
return "Alice", 30, "Engineer"
name, age = get_user_info()
# ValueError: too many values to unpack (expected 2)Fixed — unpack all three:
name, age, role = get_user_info()Fixed — use star expression to ignore extras:
name, age, *_ = get_user_info()Fixed — assign to a single variable and index:
info = get_user_info()
name = info[0]
age = info[1]This error commonly appears when a function’s return signature changes during development. You add a third return value to the function but forget to update every call site. Your IDE or linter can catch this if you use type hints:
from typing import Tuple
def get_user_info() -> Tuple[str, int, str]:
return "Alice", 30, "Engineer"With type hints, tools like mypy flag mismatched unpacking at static analysis time, before you ever run the code.
Fix 5: Fix CSV and File Parsing
When reading CSV files or splitting lines from a file, the number of columns can vary row by row. A single row with an extra comma or an unexpected delimiter causes this error.
Broken:
with open("data.csv") as f:
for line in f:
name, age, city = line.strip().split(",")
# ValueError if any row has more or fewer than 3 columnsIf a line contains Alice,30,NYC,USA, the split produces four values but you only have three variables.
Fixed — use star expression for extra columns:
with open("data.csv") as f:
for line in f:
name, age, city, *extra = line.strip().split(",")Fixed — limit the split:
with open("data.csv") as f:
for line in f:
name, age, city = line.strip().split(",", maxsplit=2)The maxsplit=2 argument tells split() to only split on the first two commas. Everything after the second comma becomes part of city. This is useful when the last field might contain the delimiter character (for example, addresses with commas).
Fixed — use the csv module:
For real-world CSV parsing, use Python’s built-in csv module instead of manual splitting. It handles quoting, escaping, and edge cases properly:
import csv
with open("data.csv") as f:
reader = csv.reader(f)
for row in reader:
if len(row) >= 3:
name, age, city = row[0], row[1], row[2]Common Mistake: Splitting on commas works fine for trivial cases, but real CSV data often contains quoted fields with commas inside them (e.g.,
"New York, NY"). Manual.split(",")breaks these fields apart and causes unpacking errors. Always use thecsvmodule orpandasfor production CSV parsing.
Fixed — validate row length:
with open("data.csv") as f:
for line_num, line in enumerate(f, 1):
parts = line.strip().split(",")
if len(parts) != 3:
print(f"Skipping malformed row {line_num}: {parts}")
continue
name, age, city = partsThis approach logs bad rows instead of crashing, which is essential for data pipelines where input quality varies.
For related file-handling issues, see Python FileNotFoundError and Python PermissionError: Errno 13.
Fix 6: Fix enumerate() Unpacking
enumerate() returns (index, element) tuples. A common mistake is forgetting the index or using the wrong number of variables.
Broken — forgetting that enumerate returns pairs:
names = ["Alice", "Bob", "Charlie"]
for name in enumerate(names):
print(name)
# name is (0, 'Alice'), not 'Alice'This does not raise an error itself, but if you later try to use name as a string, you get a TypeError. The real ValueError shows up when you try to unpack three values:
for index, first, last in enumerate(["Alice Smith", "Bob Jones"]):
print(index, first, last)
# ValueError: not enough values to unpack (expected 3, got 2)Here, enumerate() produces (0, "Alice Smith") — two values, not three.
Fixed — unpack correctly, then split the string:
for index, full_name in enumerate(["Alice Smith", "Bob Jones"]):
first, last = full_name.split()
print(index, first, last)Fixed — enumerate over pre-split data:
names = [("Alice", "Smith"), ("Bob", "Jones")]
for index, (first, last) in enumerate(names):
print(index, first, last)Notice the parentheses around (first, last) in the second example. This is nested unpacking — you unpack the enumerate tuple into index and a sub-tuple, then unpack the sub-tuple into first and last. Without those parentheses, Python tries to unpack three values from the enumerate tuple, which only has two.
Fix 7: Fix zip() Misuse
zip() combines multiple iterables element-wise into tuples. Unpacking errors arise when you expect the wrong number of elements or when the inner iterables are themselves tuples.
Broken — wrong number of variables:
names = ["Alice", "Bob"]
ages = [30, 25]
cities = ["NYC", "LA"]
for name, age in zip(names, ages, cities):
print(name, age)
# ValueError: too many values to unpack (expected 2)Each tuple from zip(names, ages, cities) contains three elements.
Fixed:
for name, age, city in zip(names, ages, cities):
print(name, age, city)Broken — zipping a list of tuples with another list:
pairs = [(1, 2), (3, 4)]
labels = ["a", "b"]
for (x, y), label in zip(pairs, labels):
# This works fine
pass
for x, y, label in zip(pairs, labels):
# ValueError — zip produces ((1, 2), "a"), not (1, 2, "a")
passFixed — use nested unpacking:
for (x, y), label in zip(pairs, labels):
print(x, y, label)When working with zip(), remember that it produces tuples with one element per input iterable. If one of those elements is itself a tuple, you need nested parentheses to unpack it.
Using zip_longest for uneven iterables:
By default, zip() stops at the shortest iterable. If your iterables have different lengths, use itertools.zip_longest:
from itertools import zip_longest
names = ["Alice", "Bob", "Charlie"]
ages = [30, 25]
for name, age in zip_longest(names, ages, fillvalue=None):
print(name, age)
# Alice 30
# Bob 25
# Charlie NoneThis avoids silent data loss from mismatched lengths.
Fix 8: Fix Nested Unpacking
Nested unpacking lets you unpack complex structures in a single assignment. The syntax mirrors the structure of the data.
Broken:
data = [("Alice", (90, 85, 92)), ("Bob", (78, 88, 95))]
for name, score1, score2, score3 in data:
print(name, score1, score2, score3)
# ValueError: not enough values to unpack (expected 4, got 2)Each element in data is a 2-tuple: ("Alice", (90, 85, 92)). Python sees two values, but you asked for four.
Fixed — nest the parentheses:
for name, (score1, score2, score3) in data:
print(name, score1, score2, score3)The parentheses around (score1, score2, score3) tell Python to unpack the inner tuple separately.
More complex nesting:
records = [
("Alice", ("Engineering", ("Python", "Go")), 95000),
("Bob", ("Marketing", ("SEO", "PPC")), 72000),
]
for name, (dept, (skill1, skill2)), salary in records:
print(f"{name} in {dept}: {skill1}, {skill2} — ${salary}")Nested unpacking is powerful but gets hard to read past two levels. For deeply nested structures, consider unpacking in steps:
for record in records:
name = record[0]
dept = record[1][0]
skills = record[1][1]
salary = record[2]Or use named tuples or dataclasses to give your data meaningful structure:
from dataclasses import dataclass
from typing import List
@dataclass
class Employee:
name: str
department: str
skills: List[str]
salary: intThis eliminates unpacking errors entirely because you access fields by name instead of position.
For related type-related issues, see Python TypeError: missing required argument and Python TypeError: ‘NoneType’ object is not subscriptable.
Still Not Working?
If none of the fixes above solve your case, try these less common scenarios.
The Data Changes at Runtime
Your unpacking code might work fine in testing but fail in production because the data shape varies. Add defensive checks:
def safe_unpack(iterable, expected):
items = list(iterable)
if len(items) != expected:
raise ValueError(
f"Expected {expected} values, got {len(items)}: {items}"
)
return itemsThis gives you a clear error message showing the actual data that caused the mismatch, making debugging much faster.
Unpacking a Generator
Generators do not have a len(), so you cannot check their length before unpacking. Convert to a list first:
def generate_values():
yield 1
yield 2
yield 3
# Risky — you don't know how many values the generator yields
a, b = generate_values() # ValueError
# Safe — convert first, then check
values = list(generate_values())
if len(values) == 2:
a, b = valuesUnpacking Inside a Comprehension
List comprehensions with unpacking follow the same rules:
# Broken
data = [(1, 2, 3), (4, 5, 6)]
result = [a + b for a, b in data] # ValueError
# Fixed
result = [a + b for a, b, _ in data]
# Or
result = [row[0] + row[1] for row in data]Unpacking a String
Strings are iterable in Python, so you can unpack them into individual characters. This frequently causes surprises:
a, b = "Hi" # Works: a='H', b='i'
a, b = "Hello" # ValueError: too many values to unpack (expected 2)If you see this error with a string, you are probably unpacking a variable you expected to be a tuple or list, but it is actually a string. Check the type of the value:
data = get_data()
print(type(data), data) # Is it actually what you expect?
a, b = dataUnpacking Across Python 2 and 3
Star expressions (*rest) only work in Python 3. If you are maintaining legacy Python 2 code, you cannot use them. Use slicing instead:
# Python 2 compatible
values = (1, 2, 3, 4, 5)
first = values[0]
rest = values[1:]Using a Try/Except Block
When unpacking data from external sources (APIs, files, user input), wrap the unpacking in a try/except to handle malformed data gracefully:
for row in data:
try:
name, age, city = row
except ValueError:
print(f"Skipping malformed row: {row}")
continueThis prevents your program from crashing on a single bad record and lets you log or collect the problematic entries for later review.
For more Python debugging strategies, see Python IndexError: list index out of range and Python SyntaxError: invalid syntax.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: AWS Lambda Unable to import module / Runtime.ImportModuleError
How to fix the AWS Lambda Runtime.ImportModuleError and Unable to import module error caused by wrong handler paths, missing dependencies, layer issues, and packaging problems.
Fix: Python TypeError: unhashable type: 'list'
Learn why Python raises TypeError unhashable type list, dict, or set and how to fix it when using dictionary keys, sets, groupby, dataclasses, and custom classes.
Fix: Django Forbidden (403) CSRF verification failed
How to fix Django 403 CSRF verification failed error caused by missing CSRF tokens, AJAX requests, cross-origin issues, HTTPS misconfig, and session problems.
Fix: FastAPI 422 Unprocessable Entity (validation error)
How to fix FastAPI 422 Unprocessable Entity error caused by wrong request body format, missing fields, type mismatches, query parameter errors, and Pydantic validation.