TypeError: can only join an iterable (tested fix)

TypeError: can only join an iterable means str.join() was given a single value, nearly always None, instead of a list of strings. We reproduced the common causes on Python 3.13 and tested each fix.

1. Cause: join() got None or a number

for value in [None, 42, 3.5, True]:
    try:
        ", ".join(value)
    except TypeError as e:
        print(f"{value!r:5} TypeError: {e}")

Output:

None  TypeError: can only join an iterable
42    TypeError: can only join an iterable
3.5   TypeError: can only join an iterable
True  TypeError: can only join an iterable

str.join() needs an iterable of strings (a list, tuple, generator...). Given a single value that is not iterable, it raises this error. The message does not name the type and is the same on Python 3.8 and 3.13, so you have to find where the value came from. It is nearly always None.

2. Joining the result of list.sort()

# list.sort() / list.append() return None, so this joins None
names = ["carol", "alice", "bob"]
try:
    print(", ".join(names.sort()))
except TypeError as e:
    print("TypeError:", e)
print(", ".join(sorted(names)))

Output:

TypeError: can only join an iterable
alice, bob, carol

list.sort(), .append(), .extend() and .reverse() change the list in place and return None. Use sorted(names), which returns a new list, or sort first and join the list on the next line.

3. A function that returns None on some paths

# A function that only returns in one branch
def tags_for(post):
    if post.get("tags"):
        return post["tags"]
for post in [{"tags": ["py", "web"]}, {"tags": []}]:
    try:
        print(" ".join(tags_for(post)))
    except TypeError as e:
        print("TypeError:", e)
print(repr(" ".join(tags_for({"tags": []}) or [])))

Output:

py web
TypeError: can only join an iterable
''

The first call works, the second hits the branch with no return and gets None. Fix the function to return [] on every path, or guard the call with or [].

4. Joining a number

# Joining digits of a number: convert to str first
n = 2026
try:
    "-".join(n)
except TypeError as e:
    print("TypeError:", e)
print("-".join(str(n)))
print("-".join(map(str, [20, 26])))

Output:

TypeError: can only join an iterable
2-0-2-6
20-26

Convert first: str(n) to join its digits, or map(str, items) to join a list of numbers. If the list itself contains numbers, you get a different error instead: sequence item 0: expected str instance, int found.

Related: object is not iterable ยท expected string or bytes-like object.

Frequently asked questions

What does can only join an iterable mean?

str.join() received a non-iterable value such as None or an int. It needs a list, tuple or other iterable of strings.

Why does ', '.join(my_list.sort()) fail?

list.sort() sorts in place and returns None. Use ', '.join(sorted(my_list)).

How do I join a list of numbers?

Convert each item: ', '.join(map(str, numbers)).

Written with AI assistance. Measured on 2026-10-23 with Python 3.13.5 on Debian (block 1 also on 3.8.20, same message): join() with None/int/float/bool, list.sort() inside join, a function with a missing return, and joining a number. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.