TypeError: items is not iterable

Node.js · updated 2026-11-03

Thrown by for...of, spread ([...x]), array destructuring, Promise.all and new Map or Set when the value has no Symbol.iterator. The name in the message is the expression that held the wrong value.

TypeError: items is not iterable
    at summarize (file:///app/src/orders.js:12:22)
    at async handler (file:///app/src/routes/orders.js:27:18)

Quick fix

Log the value right before the failing line. If it is undefined or null, find where it should have been set (a missing await, a missing field in an API response). If it is a plain object, loop over Object.values(), Object.keys() or Object.entries() instead.

  1. Log typeof value and Array.isArray(value) just before the loop.
  2. If it is a Promise, the caller is missing an await.
  3. If it is undefined, check the API response or object field it came from; default it with ?? [] only if empty is valid.
  4. If it is a plain object, iterate Object.entries(obj) instead of obj.
typescript
// Before: crashes when the API omits "items" or returns an object keyed by id
// for (const item of res.items) { ... }

const raw = (await res.json()).items;          // await the body, not the Promise
const items = Array.isArray(raw) ? raw : Object.values(raw ?? {});
for (const item of items) {
  total += item.amount;
}

Why it happens

A missing await

for (const x of fetchItems()) loops over a Promise, which is not iterable. The same happens with Promise.all(getList()) when getList is async and not awaited.

An API response without the expected field

An error body, an empty result shaped as {} or a renamed key leaves the field undefined, and the loop or spread over it throws.

Looping over a plain object

Objects are not iterable with for...of. Data keyed by id, query results converted to objects, and parsed JSON maps all need Object.values or Object.entries.

Destructuring the wrong shape

const [a, b] = useSomething() fails when the function returns an object instead of an array, a common mix-up between hooks or helpers with similar names.

Other fixes

  • Validate external responses with zod or similar so a wrong shape fails with a clear message where it enters the app.
  • for...in works on objects but iterates keys, including inherited ones; prefer Object.keys().
  • In TypeScript, avoid any on API responses so the compiler flags loops over possibly undefined values.

Same error, other wording

  • TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
  • TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
  • TypeError: data.map is not a function

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Find the "is not iterable" errors in production, show me what the value was each time (undefined, a Promise, an object) and where it came from, and fix the source instead of only adding ?? [].

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

References: MDN: TypeError: 'x' is not iterable, MDN: Iteration protocols