Skip to main content

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 in for loops, with functions like list(), tuple(), set(), sum(), min(), max(), and with the in operator (on the right side).
  • Booleans (bool): Represent truth values (True or False). 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 through True or False 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) assigns True or False to result.
  • Boolean Operators: result = condition1 and condition2 assigns True or False.
  • Type Checks: result = isinstance(obj, list) assigns True or False.
  • 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 or False.

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.