When array includes not working errors pop up, the fix usually comes from types, references, or browser coverage.
What Array Includes Actually Does
Before chasing bugs, it helps to know what Array.prototype.includes checks under the hood. The method looks through an array and compares each element to the value you pass in, using the same logic as the strict equality operator. That means no type coercion, so a string "1" never matches the number 1.
By default, the search starts at index zero and runs to the end of the array. You can pass a second argument to set a starting index, which can be handy when you only care about elements after a certain point. If the method finds at least one exact match, it returns true; if not, you see false, which often leads to the familiar sense that the method behaves in a strange way.
One helpful detail is that includes handles NaN in a friendly way. Unlike indexOf, it can find NaN inside an array, because it follows the SameValueZero comparison rules from the JavaScript specification. That small difference matters when you work with numeric data from APIs or calculations that can produce NaN.
You can think of includes as the clean, intention hinting cousin of indexOf. Where indexOf returns a position or -1, includes answers with a straight boolean. That single change lines up nicely with conditions in if statements and helps readers see that you only care whether a value exists, not where it lives.
Why Array Includes Not Working Happens In Your Code
Most time this failure shows up, the array and the code path look fine at first glance. The trouble usually lives in small mismatches between the value you think you are checking and the value that is actually stored in the array. Logging both sides in the same place almost always reveals the gap.
Many bugs fall into repeatable patterns. Sometimes the data type differs, sometimes the string casing drifts, and sometimes the array holds objects while you check with a plain value. A quick scan through common patterns helps you match your own bug to a simple fix instead of rewriting the whole feature.
| Symptom | Likely Cause | Go-To Fix |
|---|---|---|
includes returns false for obvious matches |
Type mismatch or hidden whitespace | Normalize types and trim strings before checks |
| Arrays of objects never match | Reference comparison instead of deep check | Compare by id or use some with a custom test |
| Old browsers throw an error | includes not implemented |
Add a polyfill or fall back to indexOf |
Fixes For Primitive Values In Arrays
Plenty of bug reports around this method come from arrays that only hold strings, numbers, or booleans. That is good news, because these bugs usually clear with small, repeatable checks during development.
- Match The Right Type — Confirm that the array and the value share the same type. Log
typeof valueandtypeof array[0]to spot mismatches like numbers stored as strings. - Normalize String Casing — When you compare user input to stored labels, convert both sides to one casing with
.toLowerCase()or.toUpperCase()before callingincludes. - Trim Extra Whitespace — Data from forms and files can carry leading or trailing spaces. Run
.trim()on input strings so extra spaces stop blocking matches. - Watch The From Index — If you pass a second argument to
includes, make sure that index sits inside the array length. A number that skips past the match leads to confusing false results. - Guard Against Empty Arrays — When the array comes from a filter or API call, log its length just before you run the check. An empty array always returns
false, even when the value looks valid.
Quick checks like these save time when you wire up search filters, tag pickers, or permission flags. They also make the code easier for teammates to read later, because the normalization steps sit right next to the membership test instead of hiding in a distant helper.
Be strict about how you shape numeric values as well. If an API sends ids as strings, either convert them once when loading the data or keep them as strings everywhere. Mixing numbers and numeric strings inside the same collection makes it far more likely that a late night refactor leaves a stray check that never matches.
Fixes For Arrays Of Objects And Complex Data
Arrays that store objects, arrays, or maps bring a different class of problems around this method. Under the hood, includes compares object references, not shapes or contents. Two objects with the same keys and values still count as different unless they share the same reference in memory.
When you build lists of records from APIs, those records often pass through several mapping steps. Each mapping call creates a new object, so the reference you hold outside the array rarely matches the reference inside it. Instead of passing a full object into includes, pick a stable field that identifies the record and match on that field.
- Use Some With A Predicate — Replace
array.includes(target)witharray.some(item => item.id === targetId)or another field that tags the record uniquely. - Match On Serialized Data — When you need to compare small nested objects, run
JSON.stringifyon both sides and useincludesorsomeon those strings, keeping an eye on performance. - Flatten Nested Collections — If the value hides inside nested arrays, flatten them with
flat()before the check so the search runs on a plain list. - Protect Against Mutations — When code mutates objects after adding them to an array, the comparison target may change over time. Prefer immutable updates so fields used for membership checks stay stable.
Once you shift from reference checks to field-based checks, many mysterious failures vanish. The same approach lines up well with React state patterns and Redux style stores, because both lean on ids instead of full object references.
For shared caches or cross tab data, a Map keyed by id can also help. Store each record under a single id entry, then keep arrays of those ids for lists and filters. With that layout, an includes call on the id array stays simple while lookups of the full record move through the map.
Dealing With Older Browsers And Tooling
In modern engines, Array.prototype.includes ships as a built in part of the language. Older browsers and some embedded engines still lack that method, which turns any call into a runtime error instead of a simple false. In those contexts the code crashes before a check can even run.
You can cover these gaps with a small polyfill. Many projects add a shim at the start of the bundle that defines includes when it does not already exist. The polyfill walks the array with a loop and compares values with SameValueZero rules so the behavior stays consistent on every target.
- Add A Targeted Polyfill — Drop in a short polyfill from a trusted source or use a tool like core-js through your build pipeline.
- Use Babel Or TypeScript Settings — Configure the compiler to target older runtimes so it injects helpers for missing methods, including
includeswhere needed. - Fallback To IndexOf — In very constrained setups, replace
includeswith anindexOfcheck and a comparison to-1, keeping in mind the difference aroundNaN.
It also helps to confirm which engines your users run most often. Once you know the real baseline, you can choose between a full polyfill bundle or a lighter approach that only patches includes and a few other gaps.
Writing Safer Includes Checks From The Start
Once this bug has bitten you a few times, it pays to shape new code so the same trap stays out of the way. Small habits around data shape, naming, and helpers make it less likely that array membership checks misfire when the codebase grows.
One handy tactic is to push all normalization into a tiny helper. That helper can trim strings, adjust casing, and convert known number fields from strings to numbers. Every time you reach for includes, pass both the array values and the search value through that helper so they share the same baseline before any comparison runs.
- Create A Normalizer Function — Write a utility like
normalizeTag(value)that cleans tags and labels before you store or compare them. - Store Stable Identifiers — Save ids and slugs in arrays instead of full objects so membership checks remain cheap and predictable.
- Reach For Sets When Suited — When you only need fast membership tests, wrap values in a
Setand use itshasmethod for lookups. - Document Data Shapes — Add short comments or TypeScript types that spell out what kind of values live in each array so teammates know which checks make sense.
These patterns keep the intent of the code visible. When someone reads a membership check six months later, the helper and the types hint at how the data flows, which reduces the odds that a change elsewhere silently breaks an includes call.
Debugging Checklist When Array Includes Not Working
When a stubborn bug sticks around, a short checklist keeps the work steady instead of random guesswork. Walking through the same steps every time also helps new teammates learn how includes really behaves.
- Log The Raw Values — Print the array and the searched value in the same console line so you can see types and shapes side by side.
- Confirm The Data Path — Add logs at the point where the array is built to make sure the values you expect actually arrive.
- Check Types And Casing — Compare
typeofoutputs and normalize casing before the check so you do not rely on loose equality. - Test With A Simple Array — Copy a small slice of the data into a hard coded array in a sandbox so you can reproduce the behavior in isolation.
- Swap To A Predicate — For objects, rewrite the check with
someorfindthat compares one or two stable fields. - Verify Runtime Coverage — Run a quick check like
Array.prototype.includes && [] .includesin the console to see whether the method exists at all.
This steady pattern turns Array Includes Not Working from a puzzling blocker into a series of small, fast checks. Over time, you start to spot the patterns on sight, which keeps debugging sessions shorter and keeps features shipping on schedule.
Pair that checklist with a simple unit test around every new membership rule. A tiny test that feeds in one matching case and one non matching case guards against regressions when you change how arrays are built or when you swap data sources later on. That habit keeps small bugs away.
