nodejs/node · error · TypeError

no items for cycling given

Error message

no items for cycling given

What it means

Raised by LoopContext.cycle(*args) when called with zero arguments. The {% cycle %} helper in templates cycles among the supplied values using the current loop index; with no values there is nothing to cycle through, so the runtime rejects it with TypeError.

Source

Thrown at tools/inspector_protocol/jinja2/runtime.py:369

class LoopContextBase(object):
    """A loop context for dynamic iteration."""

    _before = _first_iteration
    _current = _first_iteration
    _after = _last_iteration
    _length = None

    def __init__(self, undefined, recurse=None, depth0=0):
        self._undefined = undefined
        self._recurse = recurse
        self.index0 = -1
        self.depth0 = depth0
        self._last_checked_value = missing

    def cycle(self, *args):
        """Cycles among the arguments with the current loop index."""
        if not args:
            raise TypeError('no items for cycling given')
        return args[self.index0 % len(args)]

    def changed(self, *value):
        """Checks whether the value has changed since the last call."""
        if self._last_checked_value != value:
            self._last_checked_value = value
            return True
        return False

    first = property(lambda x: x.index0 == 0)
    last = property(lambda x: x._after is _last_iteration)
    index = property(lambda x: x.index0 + 1)
    revindex = property(lambda x: x.length - x.index0)
    revindex0 = property(lambda x: x.length - x.index)
    depth = property(lambda x: x.depth0 + 1)

    @property
    def previtem(self):

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Provide at least one argument to loop.cycle, e.g. {{ loop.cycle('even','odd') }}.
  2. Guard dynamic cycles: {% if items %}{{ loop.cycle(*items) }}{% endif %} or default to a single value.
  3. Replace an empty cycle with a literal or omit the call entirely if there is nothing to alternate.
  4. Unit-test templates against empty input sets.

Example fix

// before
{{ loop.cycle(*row_classes) }}  {% if row_classes empty %}
// after
{{ loop.cycle(*row_classes) if row_classes else 'default' }}
Defensive patterns

Strategy: validation

Validate before calling

# in Python before render
ctx['cycle_items'] = items or ['default']
# or in template: {{ loop.cycle(*items) if items else 'default' }}

Type guard

def has_cycle_items(items) -> bool:
    return len(items) > 0

Try / catch

# template-level - prefer ignore/conditional; runtime TypeError is not recoverable
{% if row_classes %}{{ loop.cycle(*row_classes) }}{% endif %}

Prevention

When it happens

Trigger: A template that calls {{ loop.cycle() }} with no arguments. Programmatic use of a LoopContext instance where the cycle list is computed at runtime and turns out empty (e.g. loop.cycle(*items) where items is []). Confusion between the loop.cycle method and the standalone jinja2.utils.Cycler.

Common situations: Dynamic cycle lists built from a variable that is sometimes empty. Refactoring a fixed {% cycle 'a','b' %} into a data-driven form and forgetting the empty case. Migration from another template engine where cycle with no args is a no-op.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/16236d37cb9bbb77. Report an issue: GitHub.