TypeError: can only concatenate str (not "int") to str means you used + between a string and an integer, like "Age: " + 31. Python never converts numbers to text automatically. Use an f-string, f"Age: {age}", or convert explicitly with str(age). If you meant to do maths with a value from input(), convert the text to a number with int() or float() instead.
The text in the brackets tells you what the other value was: "float", "NoneType", "list" and so on. When the number comes first, as in 3 + " items", the message changes to unsupported operand type(s) for +: 'int' and 'str', but the fix is the same.
All output below comes from Python 3.13.5 on my machine. I ran the two main messages on Python 3.10 and 3.14.8 too, and they were identical.
In this guide:
- Cause 1: Adding a number to a string
- Cause 2: A float, such as a price or total
- Cause 3: The number comes first
- Cause 4: Doing maths with input()
- Cause 5: A function that returns None
- Cause 6: Adding a list to a string
- Cause 7: The list version: can only concatenate list (not "int") to list
- Cause 8: join() with numbers
- Cause 9: += in a loop
- Cause 10: Mixing bytes and str
- Which conversion method is fastest?
- Quick fix table
- Frequently asked questions
Cause 1: Adding a number to a string
age = 31
print("Age: " + age)
Traceback (most recent call last):
File "c01_basic.py", line 2, in <module>
print("Age: " + age)
~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str
Python is strongly typed: + means joining for strings and addition for numbers, and it refuses to guess which one you meant. Here are five working fixes, from my favourite down:
age = 31
total = 12.5
print("Age: " + str(age))
print(f"Age: {age}, total: {total:.2f}")
print("Age:", age)
print("Age: {}".format(age))
print("Age: %d" % age)
Age: 31
Age: 31, total: 12.50
Age: 31
Age: 31
Age: 31
f-strings are the most readable and let you format numbers, such as {total:.2f} for two decimal places. My guide to f-string formatting examples has many more patterns.
Cause 2: A float, such as a price or total
total = 12.5
print("Total: " + total)
Traceback (most recent call last):
File "c02_float.py", line 2, in <module>
print("Total: " + total)
~~~~~~~~~~^~~~~~~
TypeError: can only concatenate str (not "float") to str
Same error, different type in the brackets. For money and measurements, f"Total: {total:.2f}" both converts and rounds the display, which str(total) does not do. The lexical analysis reference documents f-string syntax, including format specs like .2f.
Cause 3: The number comes first
count = 3
print(count + " items")
Traceback (most recent call last):
File "c03_reverse.py", line 2, in <module>
print(count + " items")
~~~~~~^~~~~~~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'
When the left side is an int, Python tries integer addition first and reports unsupported operand type(s) instead. Search for both messages when you debug; they have the same cause. The fix is f"{count} items".
Cause 4: Doing maths with input()
input() always returns a string, even when the user types a number. This example feeds 5 to it automatically:
import io, sys
sys.stdin = io.StringIO("5\n")
qty = input("How many? ")
print()
print(qty + 1)
How many?
Traceback (most recent call last):
File "c04_input_math.py", line 5, in <module>
print(qty + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to str
Here the goal was maths, not text, so the fix is to convert the input to a number:
import io, sys
sys.stdin = io.StringIO("5\n")
qty = int(input("How many? "))
print()
print(qty + 1)
How many?
6
Wrap int() in a try block if users can type anything, because int("five") raises ValueError. The built-in functions page documents input(), int() and str().
Cause 5: A function that returns None
def get_name():
print("looking up name...")
print("Hello " + get_name())
looking up name...
Traceback (most recent call last):
File "c05_none.py", line 4, in <module>
print("Hello " + get_name())
~~~~~~~~~^~~~~~~~~~~~
TypeError: can only concatenate str (not "NoneType") to str
get_name() printed something but never returned a value, so it returned None. The (not "NoneType") part is your clue. Add a return, or give a fallback when None is a valid result:
def get_name():
return "Ana"
print("Hello " + get_name())
name = None
print("Hello " + (name or "guest"))
Hello Ana
Hello guest
The same missing-return bug also causes 'NoneType' object is not subscriptable.
Cause 6: Adding a list to a string
tags = ["python", "errors"]
print("Tags: " + tags)
Traceback (most recent call last):
File "c06_list.py", line 2, in <module>
print("Tags: " + tags)
~~~~~~~~~^~~~~~
TypeError: can only concatenate str (not "list") to str
To show a list as text, join its items with a separator: "Tags: " + ", ".join(tags). That works because the items are strings. Numbers need one more step, shown in cause 8.
Cause 7: The list version: can only concatenate list (not "int") to list
items = [1, 2]
items = items + 3
Traceback (most recent call last):
File "c07_list_plus.py", line 2, in <module>
items = items + 3
~~~~~~^~~
TypeError: can only concatenate list (not "int") to list
Lists have the same rule: + only joins a list to another list. Use items + [3] for a new list, or items.append(3) to change it in place.
Cause 8: join() with numbers
numbers = [1, 2, 3]
print(", ".join(numbers))
Traceback (most recent call last):
File "c08_join.py", line 2, in <module>
print(", ".join(numbers))
~~~~~~~~~^^^^^^^^^
TypeError: sequence item 0: expected str instance, int found
str.join() raises its own message, sequence item 0: expected str instance, int found, because every item must already be a string. Convert them on the way in. The fixes for causes 6 to 9 are in one file:
numbers = [1, 2, 3]
print(", ".join(map(str, numbers)))
print(", ".join(str(n) for n in numbers))
tags = ["python", "errors"]
print("Tags: " + ", ".join(tags))
items = [1, 2]
print(items + [3])
log = ""
for i in range(3):
log += str(i)
print(repr(log))
1, 2, 3
1, 2, 3
Tags: python, errors
[1, 2, 3]
'012'
The str.join() documentation states that a TypeError is raised for any non-string value in the iterable.
Cause 9: += in a loop
log = ""
for i in range(3):
log += i
Traceback (most recent call last):
File "c09_augmented.py", line 3, in <module>
log += i
TypeError: can only concatenate str (not "int") to str
+= follows the same rules as +, so building a string from loop numbers fails on the first pass. Use log += str(i), as in the fix file, or better, collect the pieces in a list and join them once at the end, which is faster for long strings.
Cause 10: Mixing bytes and str
data = b"id="
print(data + "42")
Traceback (most recent call last):
File "c10_bytes.py", line 2, in <module>
print(data + "42")
~~~~~^~~~~~
TypeError: can't concat str to bytes
Bytes and text are separate types in Python 3, and the message is shorter: can't concat str to bytes. Encode the text, or decode the bytes, so both sides match:
data = b"id="
print(data + "42".encode())
print(data.decode() + "42")
b'id=42'
id=42
This usually appears with network sockets, file reads in binary mode and subprocess output. My post on Python's UTF-8 default encoding explains when you get bytes and when you get text.
Which conversion method is fastest?
I timed the four common ways to put a number into a string, one million calls each, best of five runs:
import timeit
n = 31
for stmt in ('"Age: " + str(n)', 'f"Age: {n}"', '"Age: {}".format(n)', '"Age: %d" % n'):
best = min(timeit.repeat(stmt, globals=globals(), number=1_000_000, repeat=5))
print(f"{stmt:22} {best * 1000:.0f} ns per call")
"Age: " + str(n) 44 ns per call
f"Age: {n}" 42 ns per call
"Age: {}".format(n) 66 ns per call
"Age: %d" % n 51 ns per call
The f-string and str() with + were about equally fast, and .format() was the slowest. The differences are tens of nanoseconds, so pick f-strings for readability. Timings are from one machine and will vary.
Quick fix table
| Error message | Typical line | Fix |
|---|
can only concatenate str (not "int") to str | "Age: " + age | f"Age: {age}" |
can only concatenate str (not "float") to str | "Total: " + total | f"Total: {total:.2f}" |
unsupported operand type(s) for +: 'int' and 'str' | count + " items" | f"{count} items" |
can only concatenate str (not "int") to str | input() + 1 | int(input()) + 1 |
can only concatenate str (not "NoneType") to str | "Hello " + get_name() | return a value from get_name() |
can only concatenate str (not "list") to str | "Tags: " + tags | ", ".join(tags) |
can only concatenate list (not "int") to list | items + 3 | items + [3] or items.append(3) |
sequence item 0: expected str instance, int found | ", ".join(numbers) | ", ".join(map(str, numbers)) |
can't concat str to bytes | b"id=" + "42" | b"id=" + "42".encode() |
For another everyday type error, see my guide to unhashable type: 'list'. The exceptions reference describes TypeError as an operation applied to an object of an inappropriate type, which covers every message here.
Frequently asked questions
How do I fix can only concatenate str (not "int") to str?
Use an f-string such as f"Age: {age}", or convert the number with str(age) before adding it. If you meant to do maths, convert the string to a number with int() or float() instead.
Why does Python not convert the number automatically?
Python is strongly typed. + means joining for strings and addition for numbers, and Python refuses to guess which one you want, so you must convert explicitly.
Why does input() cause this error?
input() always returns a string. Adding a number to it fails. Use int(input()) or float(input()) when you need a number.
What does can only concatenate str (not "NoneType") to str mean?
The value you added is None, usually because a function has no return statement. Return a string from the function or provide a fallback such as name or "guest".
What is the difference between this error and unsupported operand type(s) for +?
They have the same cause. You get can only concatenate when the string is on the left and unsupported operand type(s) when the number is on the left.
How do I join a list of numbers into a string?
Convert each item first: ", ".join(map(str, numbers)). str.join() only accepts strings, so join(numbers) raises sequence item 0: expected str instance, int found.
Is f-string or str() faster?
In my test both took about 42 to 44 ns per call, faster than format(). The difference is too small to matter, so choose f-strings for readability.
Last checked: 9 November 2026. Figures, settings and guidance can change, so confirm anything important with the sources linked above.