Int object is not iterable means your code tried to loop over a number; change the data shape or return an iterable value.
You hit this error when Python expects something it can loop through, but it receives a plain integer instead. It can show up in a for loop, in unpacking, in functions like sum(), or inside a library call that iterates under the hood. The fix is almost always about shape. You wanted a list, tuple, set, string, range, dict, or generator, but you handed over a single number.
This guide stays practical. You’ll see what triggers the error, how to spot the exact line that caused it, and a set of repair patterns you can reuse across scripts, notebooks, and production code.
What The Error Message Is Telling You
Python uses the word “iterable” for values that can be stepped through one item at a time. Lists are iterable. Tuples are iterable. Strings are iterable. A plain integer is not. When code tries to do iteration on an integer, Python raises TypeError with the message you’re seeing.
Iteration can be obvious, like looping. It can also be indirect. Many functions accept “a thing with many items” and quietly iterate inside. That’s why the error can appear in places that don’t look like loops.
- Read The Traceback From Bottom Up — Start at the last line; that’s where Python decided it could not iterate.
- Find The First Line In Your File — That line is usually where the integer entered a path that expects many items.
- Look For An Iteration Signal — Common signals are
for x in ...,list(...),tuple(...),set(...),zip(...), unpacking likea, b = ..., or a star like*value.
Common Places Where Integers Get Treated Like Collections
The error often comes from a mismatch between what a function returns and what the caller expects. It also happens when a variable name suggests a collection, yet it stores a count. The safest move is to check both the value and its type right where you pass it onward.
| Where It Shows Up | What You Passed | What To Do |
|---|---|---|
for item in n |
An integer count | Use range(n) or loop over a list |
sum(n) |
A single number | Sum a list like sum(nums), or skip sum |
list.extend(n) |
An integer | Use append for one item, or pass a list |
a, b = n |
An integer | Return a tuple like (a, b), not a count |
zip(n, items) |
An integer | Zip two iterables, or create a repeated iterable |
One sneaky source is JSON. A field that sometimes holds a list may hold a single number in older records. When you parse it, normalize the field to a list before you loop in your code.
- Counts Versus Lists — A name like
itemsshould hold items, not a count likelen(items). - IDs Versus Records — A name like
user_idsshould be a list of IDs, not one ID. - Return Values Versus Status Codes — If a function sometimes returns a list and sometimes returns
0, callers will trip.
Int Object Is Not Iterable Error In Python With Fast Root Causes
When you see int object is not iterable, aim to answer one question: “Where did this integer come from?” Once you find the source, the fix tends to be simple. Below are the patterns that cause the bug most often, along with clean repairs.
Looping Over A Count Instead Of A Range
A beginner-friendly trap is looping over a number you meant as a loop count. Python needs an iterable in the in slot.
# buggy
n = 5
for i in n:
print(i)
# fixed
n = 5
for i in range(n):
print(i)
- Use Range For Repeat Loops — Replace
for i in nwithfor i in range(n). - Loop Over Data When You Have It — If you already have a list, loop over the list, not its length.
Extending A List With A Single Number
extend takes an iterable and adds each element. That makes it great for adding many items. When you have one number, use append.
# buggy
nums = [1, 2]
nums.extend(3)
# fixed
nums = [1, 2]
nums.append(3)
- Pick Append For One Item —
appendadds the integer as one element. - Wrap One Item When Extend Is Required — Use
extend([3])if you must keepextend.
Unpacking A Single Integer
Unpacking expects a sequence with the right number of items. If a function returns one integer, unpacking will fail.
# buggy
x, y = 10
# fixed
x, y = (10, 20)
- Return Tuples For Multiple Outputs — Use
return a, bin the function. - Store Single Values In One Name — Use
x = 10when there is only one value.
Mixing Return Types Across Branches
This one bites even seasoned coders. A function returns a list on success, but returns an integer on failure. Then a caller iterates the result and crashes.
def get_scores(user_id):
data = fetch_scores(user_id)
if data is None:
return 0 # buggy shape
return data
def get_scores(user_id):
data = fetch_scores(user_id)
if data is None:
return [] # fixed shape
return data
- Keep A Stable Shape — Return an empty list instead of
0when the caller loops. - Use Exceptions For Errors — Raise an error for failure states instead of returning a number.
Repair Patterns You Can Apply In Minutes
Once you know where the integer enters an iterable path, pick a repair pattern that matches your intent. These are the ones you’ll use most.
Wrap A Single Value Into A One-Item Iterable
If downstream code is built around iterables, wrapping can be the cleanest option. It keeps call sites simple and keeps the data shape steady.
- Use Square Brackets For A List — Turn
ninto[n]when one item is fine. - Use A Trailing Comma For A Tuple — Write
(n,)when you need a tuple. - Use Set Braces With Care — Use
{n}for a set when you need no duplicates.
Generate A Sequence From A Count
If the integer is a count, make an iterable that represents the repetition. The usual choice is range. It’s memory-friendly and works in loops and comprehensions.
- Use Range For Indexes —
range(n)yields 0 through n-1. - Use Range With A Start —
range(start, stop)matches many slice-style tasks. - Use Repeat For Same Value —
itertools.repeat(n, times)yields the same value many times.
Convert The Upstream Value To The Right Type
Sometimes the integer is a symptom of a parsing step that lost structure. Say you split a string but then cast one part to int too early. In those cases, keep the data as a list until the moment you need the number.
- Delay Int Casting — Keep strings in a list, then cast each item during iteration.
- Cast Collections, Not Scalars — Use
map(int, parts)or a list comprehension to build a list of ints. - Validate Input Shape — If a function accepts “one or many,” normalize to a list right away.
Debugging Steps That Pinpoint The Real Line
When the traceback points into a library, it can feel like the bug is outside your code. In practice, your code still passed the integer in. Use a tight workflow to find the handoff point and fix it once.
Print Type And Value Right Before The Crash
Add a single print at the call site. Remove it after the fix. Keep it surgical so you don’t drown in logs.
print(value, type(value))
- Check The Shape At Boundaries — Print right before you pass a value into a function or loop.
- Check After Parsing — Print right after reading files, JSON, forms, or CLI args.
Use Guard Clauses To Fail Early
Guards can turn a confusing deep traceback into a clear local error. They also document what your function expects.
from collections.abc import Iterable
def process(items):
if isinstance(items, int):
raise TypeError("process() needs an iterable, not an int")
# proceed with iteration
- Reject Int Inputs — If an integer makes no sense, fail right away.
- Normalize One Or Many — If you accept either, convert int to
[int]near the top.
Trace The Data Back Through Assignments
Once you know a name holds an integer, jump back to where that name was set. Look for calls to len(), integer casts, counters, or numeric defaults.
- Search For The Variable Name — Scan for reassignment that changes a list into a count.
- Watch For Shadowing — A loop index named
itemscan overwrite an outer list nameditems. - Check Function Returns — A return that swaps between list and int is a common trigger.
Patterns That Prevent The Error From Coming Back
After you fix the immediate crash, a small bit of structure can keep the same bug from reappearing in a month. You don’t need heavy ceremony. A few habits go a long way.
Name Variables By Shape
Names can carry shape hints. Plural names suggest many items. Singular names suggest one item. That makes it easier to spot a mismatch while reading.
- Use Plurals For Iterables —
users,scores,rows. - Use Count Suffixes For Numbers —
user_count,row_total. - Use Id For One Identifier —
user_idfor one int,user_idsfor many.
Keep Return Types Stable
If callers loop over your return value, always return an iterable, even when the result is empty. Reserve integers for counts and status codes that callers never iterate.
- Return Empty Lists On No Data — An empty list is safe to loop over.
- Raise Errors On Failure — Exceptions keep shapes consistent and keep failures loud.
- Document The Contract — A short docstring that states the return type can prevent misuse.
Use Type Hints And Static Checks
Type hints can catch “int passed where iterable expected” before runtime. Even if you don’t run a full type checker, hints improve editor feedback and code review clarity.
from typing import Iterable
def total(values: Iterable[int]) -> int:
return sum(values)
- Add Hints At Public Boundaries — Start with functions that are called from many places.
- Run A Type Checker In CI — Tools like mypy can flag shape mismatches early.
If you’re seeing this crash in a new codebase, fix the first one, then search for the same pattern elsewhere. Once you train your eyes to spot “count passed as collection,” the int object is not iterable error stops being mysterious and turns into a quick shape check.
