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 inforloops, with functions likelist(),tuple(),set(),sum(),min(),max(), and with theinoperator (on the right side). - Booleans (
bool): Represent truth values (TrueorFalse). 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
forloop: Trying to loop throughTrueorFalsemakes 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
try:
for item in state:
print(item)
except TypeError as e:
print(f"For loop error: {e}")
try:
items = list(state)
print(items)
except TypeError as e:
print(f"list() error: {e}")
try:
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/Falseinstead of the expected list?
Example with Error:
def get_users():
if user_count > 0: return user_list
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:
def get_users_safe():
user_list = [] # Assume this is populated somehow
user_list = [{'active': True}, {'active': False}] if len(user_list) == 0 else user_list
return user_list if user_list else []
users = get_users_safe() # Guaranteed to be a list
print(f"Users: {users}")
all_active = all(user['active'] for user in users if isinstance(user, dict))
print(f"All active? {all_active}") # Output: False
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
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):
print(f"Data is a boolean ({data}), cannot iterate. Handling appropriately.")
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
try:
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:
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:
def load_config_safe():
config_data = {'user_setting': 'abc', 'mode': 'test'}
return config_data
config = load_config_safe() # Guaranteed to be a dict (iterable over keys)
print(f"Config loaded: {config}")
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.")
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.
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)assignsTrueorFalsetoresult. - Boolean Operators:
result = condition1 and condition2assignsTrueorFalse. - Type Checks:
result = isinstance(obj, list)assignsTrueorFalse. - Functions Returning Status: Functions that check something might return
True/Falseinstead of the data itself. - Accidental Reassignment: Overwriting a list/string variable with
TrueorFalse.
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:
iterator = iter(obj)
print(f"{repr(obj)} (type: {type(obj)}) is iterable.")
return True
except TypeError:
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: FalseConclusion
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.