Short answer
Log the value just before the line that throws. If it is a plain object, loop over Object.entries(obj) or Object.values(obj) instead. If it is a Promise, add await. If it is undefined, the data has not loaded or the property name is wrong, so default it (list ?? []) and fix where it comes from. For const [a, b] = something, check that something really returns an array, not an object.
What the value really is, and the fix
01
A plain object in for...of or spread
“In JavaScript, Objects are not iterable unless they implement the iterable protocol.” MDN, TypeError: 'x' is not iterable
Objects are not lists. API responses often wrap the list ({ items: [...] }), and maps of id to record are objects too. Loop over the property that holds the array, or over Object.entries.
for (const item of response.items) { /* ... */ } for (const [id, user] of Object.entries(usersById)) { /* ... */ }02
undefined: data that has not arrived
On the first render, before a fetch finishes, or when a property name is wrong, the value is undefined. Give it a default where it enters your code, and fix the source if it should always be there.
const items = data?.items ?? []; return items.map((item) => <Row key={item.id} item={item} />);03
A Promise that was never awaited
“In order to be iterable, an object must implement the [Symbol.iterator]() method” MDN, Iteration protocols
An async function returns a Promise, not the array inside it. A Promise is an object without that method, so looping over it throws. Await it first.
// wrong const rows = getRows(); for (const row of rows) {} // right const rows = await getRows();04
Array destructuring from something that is not an array
const [value, setValue] = useMyHook() throws when the hook returns an object or nothing. React context is a common case: a provider that passes an object, or a component outside the provider that gets the default value. Destructure with braces for objects, and check the provider.
const { user, setUser } = useContext(UserContext);
Checked against the vendor’s docs on : MDN: TypeError: 'x' is not iterable; MDN: Iteration protocols.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: JavaScript “x is not a function” · “Cannot read properties of undefined” · “Cannot destructure property of undefined”