The int object is not subscriptable error means you indexed a number like a list; fix it by indexing the real container or keeping the value as a container.
You’ll see this error when Python reads square brackets right after an integer and stops the program. It’s not being picky. It’s saving you from code that “runs” while doing the wrong thing.
If you’ve ever thought, “This variable was a list a second ago,” you’re already close to the fix. Most cases come down to one issue: a value that changed shape without you noticing.
What “Not Subscriptable” Means In Plain Python
In Python, brackets are for pulling an item out of a container. Lists, tuples, strings, dictionaries, and many library objects can be accessed with []. An int can’t, since it’s a single number, not a collection.
That’s why code such as 42[0] explodes. Python can’t interpret “index zero of forty-two,” so it throws TypeError: 'int' object is not subscriptable and points at the brackets.
Quick check: Look one token to the left of the [. Ask yourself what that thing is right now, not what you meant it to be.
How To Confirm The Type Fast
Before you change code, confirm the type at the crash line. A name that held a list earlier can hold a number later, especially after a refactor.
- Print The Type — Add
print(type(x), x)on the line before the crash, run once, then remove it. - Step Through Once — Use a debugger breakpoint right above the failing line and watch the variable update.
- Search For Overwrites — Use your editor search for
x =and scan where the value changes.
Int Object Is Not Subscriptable In Python When Data Shapes Drift
The most common cause is “shape drift.” You expect a container, yet you’re holding a single number by the time you index it. This shows up in loops, parsing, and code that started small and grew.
It can feel confusing because the variable name still sounds like a container. Your brain reads values[0] and assumes “values is a list.” Python reads it and sees “values is an int.”
Common Triggers You Can Spot Right Away
| Trigger | What It Looks Like | Fix Direction |
|---|---|---|
| Indexing A Number | n[0] |
Index the real container or keep n as a container |
| Wrong Unpack | a, b = item then a[0] |
Confirm item is a sequence and name parts clearly |
| Return Type Surprise | row = func() then row[1] |
Align caller code with what the function returns |
| Name Shadowing | list = 3 then list[0] |
Rename variables that collide with built-ins or earlier containers |
| Math Then Brackets | (x + y)[0] |
Index before math, or store the container first |
Once you know which bucket you’re in, the fix is usually small. The key is changing the source of the wrong shape, not just patching the crash line.
Fix Patterns That Solve The Error Cleanly
When you see brackets after a variable, there are only a few valid intentions. You either meant to index a list or tuple, grab a dict value by key, slice a string, or select from an array-like object.
Pick your intention, then make the data match it. Guessing often “fixes” the error while breaking the result.
Pattern 1: You Meant To Index A List, Yet You Stored One Number
This happens when you reduce a list to a single value and keep using the old name out of habit.
# You start with a list
scores = [10, 20, 30]
# Later you overwrite the same name with one number
scores = scores[0]
# Then you try to index it again
print(scores[0]) # TypeError
- Keep Names Honest — Use
scoresfor the list andscorefor one number. - Index Before Reducing — If you only need one element, pull it out once, then use it as a number.
- Fix The Overwrite — If a helper should return a list, keep it returning a list and adjust the helper, not every caller.
Pattern 2: You Meant A Dict Key, Yet You’re Holding The Id
Another common slip is mixing “the object” with “a field from the object.” You might expect user["id"], then later store only the id back into user.
Deeper fix: Keep the dict and the id as separate variables. That one choice removes a lot of confusion in larger files.
- Use Clear Pair Names —
userfor the dict,user_idfor the integer. - Validate At Boundaries — If a function expects a dict, check it early and fail with a readable message.
- Parse Once — Convert raw input into a dict structure in one place, then pass that structure around.
Pattern 3: You Thought A Function Returned A Sequence
Many functions return a single count, boolean, or id. If you treat that return as a list, you’ll index an int and hit the error.
# This returns an int
count = len(items)
# Treating it like a list triggers the crash
print(count[0])
- Check The Return — Read the function docstring or the implementation and confirm the return type.
- Split “One” And “Many” Helpers — Use separate functions for one item versus a list of items.
- Add Type Hints — A hint like
def count_items(...) -> intlets many editors warn you before runtime.
Debug Walkthroughs In The Usual Trouble Spots
Context is what makes the fix stick. These are the spots where int object is not subscriptable shows up most often, even for experienced Python devs.
Loops Where A Variable Changes Meaning
A loop variable is usually one element. If you later treat it as the whole list, you’ll end up indexing a scalar.
nums = [5, 6, 7]
for num in nums:
# num is an int on every iteration
print(num[0]) # TypeError
- Index The Container — Use
nums[0]outside the loop when you want the first element. - Keep One Level Per Block — A block handling one element should not switch to list-level indexing.
- Log One Iteration — Print type and value once to confirm your mental model, then delete the print.
CSV And JSON Parsing That Collapses A Row Early
Parsing code often pulls one column too soon. Later code still assumes it has the full row.
- Store The Full Row First — Keep
rowas a list or dict, then storeage = row[2]in a new name. - Guard Missing Fields — Check length or key presence before indexing so bad input fails cleanly.
- Convert Types Once — Convert string digits to ints in one section, then keep them as ints.
Pandas And Numpy Cases Where You End Up With A Scalar
In data code, you can select a single cell and end up with a scalar. Scalars don’t behave like arrays, so bracket indexing may break once you’ve reduced the shape.
- Inspect Selection Results — Print the type right after selection to see if you got a Series, array, or scalar.
- Choose One Access Style — Stick with
.locor.ilocand be clear when you want a slice versus one cell. - Delay Scalar Conversion — Keep array-like objects until the final step if later code expects indexing.
Prevention Habits That Stop Repeat Errors
Fixing the crash line is step one. Preventing the next one is about habits that keep your data shapes clear even when the file changes.
Naming That Makes Wrong Indexing Feel Wrong
Names are your early warning system. If a variable called scores turns into a single number, that mismatch should look strange right away.
- Use Plurals For Containers —
users,items,scoresfor lists, tuples, dicts, and arrays. - Use Singular For One Value —
user,item,scorefor one element or one scalar. - Avoid Built-In Names — Don’t name variables
list,dict,int, orsum.
Type Hints And Editor Checks That Catch It Early
Static checks can catch “indexing an int” before you run the program. That’s especially handy when the failing path only happens with certain inputs.
- Hint Return Types First — Start with function returns, then add hints to main data structures.
- Turn On Warnings — Let your editor flag suspicious subscripts once it knows types.
- Add Small Assertions — A simple
assert isinstance(rows, list)can act as a tripwire in scripts.
Guard Rails For Inputs That Flip Types
User input is where types often flip. A CLI argument starts as text, then becomes a number. If you store that number back into a name that used to hold a list, you set up a later crash.
- Parse Into New Names — Keep
raw_valueandparsed_valueseparate. - Check Range Before Indexing — Validate indexes and lengths before you pull items out of a container.
- Raise Clear Errors — Say what type you got and what you expected, so the next person fixes it fast.
Int Object Is Not Subscriptable Quick Checklist
When you just want the fix and you’re staring at a traceback, this checklist keeps you focused on the right step each time.
- Find The Brackets — Go to the traceback line and locate the exact
[that triggered the crash. - Point At The Left Side — Identify the value right before the bracket and name it.
- Confirm The Type — Print
type(x)or inspect it in your debugger at that line. - Pick The Intended Shape — Decide “number” or “container,” then change the code to match.
- Fix The Source — Find where the value became an int and adjust that spot, not just the crash line.
- Lock The Fix In — Rename, add a type hint, or add a small assertion to prevent repeats.
If you still see int object is not subscriptable after one fix, search for a second overwrite of the same variable name on another branch. That’s a classic “it worked once” trap.
Once you treat names and shapes as part of your code’s story, this error stops feeling random. It becomes a clear signal that your data changed without your code changing with it.
