How to Resolve Python "TypeError: 'bool' object is not iterable" and "TypeError: argument of type 'bool' is not iterable"
Python's boolean values, True
and False
, represent logical states. They are simple, scalar values, not collections or sequences of items. Errors like TypeError: 'bool' object is not iterable
or TypeError: argument of type 'bool' is not iterable
arise when you attempt to use a boolean value in a context that requires an iterable object, i.e. something that can be looped over, like a list, string, tuple, or dictionary.
This guide explains why booleans are not iterable and provides solutions for common scenarios where these errors occur, such as loops and membership tests.
Understanding the Error: Iterables vs. Booleans
- Iterables: Objects capable of returning their members one at a time. Examples include lists (
[]
), tuples (()
), strings (""
), dictionaries ({}
- iterates keys by default), sets ({}
), and file objects. You can use them infor
loops, with functions likelist()
,tuple()
,set()
,sum()
,min()
,max()
, and with thein
operator (on the right side). - Booleans (
bool
): Represent truth values (True
orFalse
). They are single, indivisible values and cannot be iterated over.
The TypeError
occurs because you've supplied a bool
(True
or False
) where Python expected an iterable object.
Error 1: TypeError: 'bool' object is not iterable
This version typically occurs when attempting to iterate directly over a boolean or pass it to functions expecting iterables.
Cause: Using a Boolean in a for
loop or with Iterator Functions
for
loop: Trying to loop throughTrue
orFalse
makes no sense, as they don't contain multiple items.- Iterator Functions/Constructors: Functions like
list()
,tuple()
,set()
,dict()
,sum()
,min()
,max()
,sorted()
, etc., expect an iterable argument to process its elements. Passing a boolean fails this requirement.
state = True # A boolean variable
# Error Scenario 1: For loop
try:
# ⛔️ TypeError: 'bool' object is not iterable
for item in state:
print(item)
except TypeError as e:
print(f"For loop error: {e}")
# Error Scenario 2: list() constructor
try:
# ⛔️ TypeError: 'bool' object is not iterable
items = list(state)
print(items)
except TypeError as e:
print(f"list() error: {e}")
# Error Scenario 3: sum() function
try:
# ⛔️ TypeError: 'bool' object is not iterable
total = sum(state) # sum expects an iterable of numbers
print(total)
except TypeError as e:
print(f"sum() error: {e}")
Solution: Ensure the Variable Holds an Iterable (Fix the Source)
The best solution is usually to find why the variable holds a boolean when you expected an iterable (list, string, etc.) and fix that logic.
- Did a comparison accidentally overwrite your list variable (e.g.,
my_list = (len(my_list) == 0)
)? - Did a function return
True
/False
instead of the expected list?
Example with Error:
# --- Problematic Code ---
def get_users():
if user_count > 0: return user_list
# Implicitly returns None if user_count is 0
users = get_users() # Could be None
if users == None: users = [] # Need to handle None explicitly
users_status = all(user.active for user in users) # Might assign True/False
for user in users_status: # ⛔️ Error if users_status is bool
...
Correct Example:
# --- Corrected Logic Example ---
def get_users_safe():
user_list = [] # Assume this is populated somehow
# Simulate populating
user_list = [{'active': True}, {'active': False}] if len(user_list) == 0 else user_list
# ✅ Always return a list (even if empty)
return user_list if user_list else []
users = get_users_safe() # Guaranteed to be a list
print(f"Users: {users}")
# Perform check, store result separately
all_active = all(user['active'] for user in users if isinstance(user, dict))
print(f"All active? {all_active}") # Output: False
# Iterate over the original list, not the boolean result
print("Iterating over users list:")
for user in users:
print(user)
Output:
Users: [{'active': True}, {'active': False}]
All active? False
Iterating over users list:
{'active': True}
{'active': False}
Solution: Check Type Before Iterating
If the variable might sometimes be a boolean and sometimes an iterable, check its type before attempting iteration.
data = True # Could also be ['a', 'b'] sometimes
# ✅ Check type before iterating
if isinstance(data, (list, tuple, str, set, dict)): # Check against common iterable types
print(f"Data ({type(data)}) is iterable:")
for item in data:
print(f" Item: {item}")
elif isinstance(data, bool):
# This block runs
print(f"Data is a boolean ({data}), cannot iterate. Handling appropriately.")
# Add logic here for when data is a boolean
else:
print(f"Data is of unexpected type: {type(data)}")
Error 2: TypeError: argument of type 'bool' is not iterable
This specific wording usually comes from using the membership test operators (in
or not in
) with a boolean value on the right-hand side.
Cause: Using in
or not in
with a Boolean on the Right Side
The in
operator checks if an element exists within a container (an iterable). It requires the object on the right side to be iterable.
is_enabled = True # A boolean variable
# Error Scenario
try:
# ⛔️ TypeError: argument of type 'bool' is not iterable
# Checking if 'some_setting' is 'in' True/False makes no sense
if 'some_setting' in is_enabled:
print("Setting found.")
except TypeError as e:
print(e)
Solution: Ensure the Right-Side Operand is an Iterable
Again, the fundamental fix is to ensure the variable on the right side of in
actually holds the iterable (list, string, tuple, set, dict keys) you intended to search within.
Example with Error:
# --- Problematic Code ---
config_loaded = load_config() # Assume this might return True/False on failure
if 'user_setting' in config_loaded: # ⛔️ Error if config_loaded is bool
...
Correct Example:
# --- Corrected Logic Example ---
def load_config_safe():
# Simulate loading, return {} if failed, actual config dict otherwise
config_data = {'user_setting': 'abc', 'mode': 'test'}
# return False # Simulate failure
return config_data
config = load_config_safe() # Guaranteed to be a dict (iterable over keys)
print(f"Config loaded: {config}")
# Check if 'user_setting' is a key in the config dictionary
if isinstance(config, dict) and 'user_setting' in config:
print("'user_setting' key found in config.") # This runs
else:
print("'user_setting' key not found or config is not a dict.")
# Check if 'admin' is a value in a list (example of correct 'in' usage)
allowed_roles = ['admin', 'editor', 'viewer']
user_role = 'editor'
if user_role in allowed_roles:
print(f"'{user_role}' is an allowed role.")
Output:
Config loaded: {'user_setting': 'abc', 'mode': 'test'}
'user_setting' key found in config.
'editor' is an allowed role.
Make sure the variable you use with in
or not in
actually holds the collection you want to search.
Solution: Check Type Before Using in
/ not in
If a variable might hold a boolean or an intended iterable, check its type first.
potential_iterable = False # Could be bool or list, etc.
# Check type before using 'in'
if isinstance(potential_iterable, (list, tuple, str, set, dict)):
if 'target' in potential_iterable:
print("'target' found in iterable.")
else:
print("'target' not found in iterable.")
elif isinstance(potential_iterable, bool):
print("Variable holds a boolean, 'in' check skipped.")
else:
print(f"Variable holds unexpected type: {type(potential_iterable)}")
Output:
Variable holds a boolean, 'in' check skipped.
Common Sources of Unexpected Boolean Values
- Comparisons:
result = (x == y)
assignsTrue
orFalse
toresult
. - Boolean Operators:
result = condition1 and condition2
assignsTrue
orFalse
. - Type Checks:
result = isinstance(obj, list)
assignsTrue
orFalse
. - Functions Returning Status: Functions that check something might return
True
/False
instead of the data itself. - Accidental Reassignment: Overwriting a list/string variable with
True
orFalse
.
Checking if an Object is Iterable (General)
You can use a try...except TypeError
block with the built-in iter()
function to check if an object supports iteration.
def check_iterability(obj):
try:
# Attempt to get an iterator from the object
iterator = iter(obj)
print(f"{repr(obj)} (type: {type(obj)}) is iterable.")
return True
except TypeError:
# iter() raises TypeError for non-iterable objects
print(f"{repr(obj)} (type: {type(obj)}) is NOT iterable.")
return False
check_iterability("hello") # Output: True
check_iterability([1, 2]) # Output: True
check_iterability({'a': 1}) # Output: True
check_iterability(True) # Output: False
check_iterability(123) # Output: False
check_iterability(None) # Output: False
Conclusion
The TypeError: 'bool' object is not iterable
and TypeError: argument of type 'bool' is not iterable
errors occur when you treat a boolean value (True
or False
) as a collection or sequence that can be looped over or searched within using in
.
The core solution is to ensure the variable you are iterating over or using with the in
operator actually holds an iterable object (list, tuple, string, dict, set, etc.) and not a simple boolean True
or False
. Trace the variable's assignment to find where it might have been incorrectly assigned a boolean value instead of the intended iterable, or add type checks (isinstance
) before attempting iteration or membership tests if the variable's type can vary.