TheAlgorithms/Python · error · ValueError

Expecting an iterable object but got an non-iterable type {p

Error message

Expecting an iterable object but got an non-iterable type {points}

What it means

Raised by _validate_input() in divide_and_conquer/convex_hull.py:179 when the points argument has no __iter__ attribute — i.e. passing a single scalar like an int, float, or None where an iterable of (x, y) points is required. It is the first of two validation stages: non-iterable raises this; an empty iterable raises the sibling 'Expecting a list of points' error.

Source

Thrown at divide_and_conquer/convex_hull.py:179

    >>> _validate_input([[1, 2]])
    [(1.0, 2.0)]
    >>> _validate_input([(1, 2)])
    [(1.0, 2.0)]
    >>> _validate_input([Point(2, 1), Point(-1, 2)])
    [(2.0, 1.0), (-1.0, 2.0)]
    >>> _validate_input([])
    Traceback (most recent call last):
        ...
    ValueError: Expecting a list of points but got []
    >>> _validate_input(1)
    Traceback (most recent call last):
        ...
    ValueError: Expecting an iterable object but got an non-iterable type 1
    """

    if not hasattr(points, "__iter__"):
        msg = f"Expecting an iterable object but got an non-iterable type {points}"
        raise ValueError(msg)

    if not points:
        msg = f"Expecting a list of points but got {points}"
        raise ValueError(msg)

    return _construct_points(points)


def _det(a: Point, b: Point, c: Point) -> float:
    """
    Computes the sign perpendicular distance of a 2d point c from a line segment
    ab. The sign indicates the direction of c relative to ab.
    A Positive value means c is above ab (to the left), while a negative value
    means c is below ab (to the right). 0 means all three points are on a straight line.

    As a side note, 0.5 * abs|det| is the area of triangle abc

    Parameters

View on GitHub (pinned to f5988cc097)

Solutions

  1. Always pass a collection of coordinate pairs: convex_hull([(x1,y1),(x2,y2),...])
  2. Check for None explicitly before calling when the data source can return None
  3. Guard with isinstance(points, (list, tuple)) and verify each element is a length-2 sequence

Example fix

// before
hull = convex_hull(point)  # point = (3, 4) -> silently wrong; point = 3 -> ValueError

# after
points = [point] if isinstance(point, tuple) and len(point) == 2 else point
hull = convex_hull(points)
Defensive patterns

Strategy: type-guard

Validate before calling

if points is None or isinstance(points, (int, float)):
    raise ValueError('points must be an iterable of (x, y) pairs')
hull = convex_hull(points)

Type guard

def is_points_collection(points) -> bool:
    return hasattr(points, '__iter__') and len(points) > 0 and all(
        hasattr(p, '__len__') and len(p) == 2 for p in points
    )

Try / catch

try:
    hull = convex_hull(points)
except ValueError as e:
    if 'non-iterable' not in str(e) and 'list of points' not in str(e):
        raise
    hull = None

Prevention

When it happens

Trigger: convex_hull(1), convex_hull(None), or convex_hull((3, 4)) where a single point tuple is passed instead of a collection of points — note a tuple IS iterable, so a lone point is accepted and misinterpreted, not rejected here.

Common situations: Calling the hull function with the result of a function that sometimes returns None (empty search), or unwrapping a list one level too many before passing it in.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/ccde87ede3479854. Report an issue: GitHub.