TheAlgorithms/Python · error · TypeError

next_side must be a Side or None.

Error message

next_side must be a Side or None.

What it means

Raised by Side.__post_init__ (geometry/geometry.py:75) when next_side is neither a Side instance nor None. next_side is used to chain sides into a polygon outline, so the type must be exactly Side or None (checked against (Side, NoneType)).

Source

Thrown at geometry/geometry.py:75

        ...
    TypeError: angle must be an Angle object.
    >>> Side(5, Angle(90), "Invalid next_side")
    Traceback (most recent call last):
        ...
    TypeError: next_side must be a Side or None.
    """

    length: float
    angle: Angle = field(default_factory=Angle)
    next_side: Side | None = None

    def __post_init__(self) -> None:
        if not isinstance(self.length, (int, float)) or self.length <= 0:
            raise TypeError("length must be a positive numeric value.")
        if not isinstance(self.angle, Angle):
            raise TypeError("angle must be an Angle object.")
        if not isinstance(self.next_side, (Side, NoneType)):
            raise TypeError("next_side must be a Side or None.")


@dataclass
class Ellipse:
    """
    A geometric Ellipse on a 2D surface

    >>> Ellipse(5, 10)
    Ellipse(major_radius=5, minor_radius=10)
    >>> Ellipse(5, 10) is Ellipse(5, 10)
    False
    >>> Ellipse(5, 10) == Ellipse(5, 10)
    True
    """

    major_radius: float
    minor_radius: float

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass None (the default) when there is no successor: Side(5)
  2. Construct the next Side first, then link: second = Side(3); first = Side(5, next_side=second)
  3. When deserializing, rebuild the Side chain from raw data with a small loader function instead of feeding raw dicts/tuples to the dataclass

Example fix

# before
side = Side(5, next_side=(3, Angle(45)))

# after
side = Side(5, next_side=Side(3, angle=Angle(45)))
Defensive patterns

Strategy: type-guard

Validate before calling

from geometry.geometry import Side

next_side = None if raw_next is None else raw_next
assert next_side is None or isinstance(next_side, Side)
side = Side(length, angle=angle, next_side=next_side)

Type guard

def is_side_or_none(value: object) -> bool:
    from geometry.geometry import Side
    return value is None or isinstance(value, Side)

Prevention

When it happens

Trigger: Passing a number, tuple, or list as next_side, e.g. Side(5, next_side=7) or Side(5, next_side=(3, Angle(45))). Also passing a subclass-like duck type that is not an actual Side.

Common situations: Building polygons programmatically and passing a coordinate tuple instead of the next Side; deserializing polygon data where next_side arrives as a dict; assuming any object with length/angle attributes would be accepted (structural typing is not used here).

Related errors


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