nodejs/node · error · TypeError
Loop length for some iterators cannot be lazily calculated i
Error message
Loop length for some iterators cannot be lazily calculated in async mode
What it means
Raised by AsyncLoopContext.length (asyncsupport.py) when loop.length / loop.revindex / loop.last and similar length-derived attributes are requested during async iteration but no upfront length was supplied. Unlike sync mode, an async iterator cannot be cheaply len()-ed, so the length is unknown and these attributes are unavailable.
Source
Thrown at tools/inspector_protocol/jinja2/asyncsupport.py:202
yield item
return
for item in iterable:
yield item
class AsyncLoopContext(LoopContextBase):
def __init__(self, async_iterator, undefined, after, length, recurse=None,
depth0=0):
LoopContextBase.__init__(self, undefined, recurse, depth0)
self._async_iterator = async_iterator
self._after = after
self._length = length
@property
def length(self):
if self._length is None:
raise TypeError('Loop length for some iterators cannot be '
'lazily calculated in async mode')
return self._length
def __aiter__(self):
return AsyncLoopContextIterator(self)
class AsyncLoopContextIterator(object):
__slots__ = ('context',)
def __init__(self, context):
self.context = context
def __aiter__(self):
return self
async def __anext__(self):
ctx = self.contextView on GitHub (pinned to 1b2de5e052)
Solutions
- Materialize the async iterator into a list before the loop so the length is known: `{% for x in await to_list(source) %}`.
- Pre-compute the length and pass it explicitly if the loop construct supports a length argument.
- Rewrite the template body to not depend on total count (use loop.index / loop.index0 only, which need no length).
Example fix
{# before #}
{% for x in async_source %}{{ loop.length }}{% endfor %}
{# after #}
{% set items = async_source | list %}
{% for x in items %}{{ items | length }}{% endfor %} Defensive patterns
Strategy: validation
Validate before calling
async def materialize(ait):
out = []
async for x in ait:
out.append(x)
return out
# in template: {% set items = await to_list(source) %} then iterate `items` Prevention
- Avoid loop.length/revindex/last over async iterators; use loop.index/index0.
- Materialize async iterators into a list before the loop when counts are needed.
- Document which template helpers require a known length.
When it happens
Trigger: In an async-enabled template, iterating `{% for x in some_async_gen %}` and inside the loop body referencing `{{ loop.length }}`, `{{ loop.revindex }}`, `{{ loop.last }}`, or `{{ loop.first }}`-style helpers that need the total count.
Common situations: Iterating an async generator / async DB cursor in a template and trying to show 'item N of M' progress; reusing a sync template that used loop.length against a now-async data source.
Related errors
- Template module attribute is unavailable in async mode
- no items for cycling given
- Tried to call non recursive loop. Maybe you forgot the 'rec
- The environment was not created with async mode enabled.
- extended multiple times
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/7671e199052e09f7.
Report an issue: GitHub.