TheAlgorithms/Python · error · TypeError

degrees must be a numeric value between 0 and 360.

Error message

degrees must be a numeric value between 0 and 360.

What it means

Raised by Angle.__post_init__ in geometry/geometry.py when degrees is not int/float or lies outside [0, 360] (inclusive both ends). Angle is a dataclass used by Side to orient polygon edges; the check runs at construction. Quirk: it raises TypeError even for pure range violations (Angle(361)), which is unconventional — most libraries use ValueError for out-of-range values.

Source

Thrown at geometry/geometry.py:34

    >>> Angle()
    Angle(degrees=90)
    >>> Angle(45.5)
    Angle(degrees=45.5)
    >>> Angle(-1)
    Traceback (most recent call last):
        ...
    TypeError: degrees must be a numeric value between 0 and 360.
    >>> Angle(361)
    Traceback (most recent call last):
        ...
    TypeError: degrees must be a numeric value between 0 and 360.
    """

    degrees: float = 90

    def __post_init__(self) -> None:
        if not isinstance(self.degrees, (int, float)) or not 0 <= self.degrees <= 360:
            raise TypeError("degrees must be a numeric value between 0 and 360.")


@dataclass
class Side:
    """
    A side of a two dimensional Shape such as Polygon, etc.
    adjacent_sides: a list of sides which are adjacent to the current side
    angle: the angle in degrees between each adjacent side
    length: the length of the current side in meters

    >>> Side(5)
    Side(length=5, angle=Angle(degrees=90), next_side=None)
    >>> Side(5, Angle(45.6))
    Side(length=5, angle=Angle(degrees=45.6), next_side=None)
    >>> Side(5, Angle(45.6), Side(1, Angle(2)))  # doctest: +ELLIPSIS
    Side(length=5, angle=Angle(degrees=45.6), next_side=Side(length=1, angle=Angle(d...
    >>> Side(-1)
    Traceback (most recent call last):

View on GitHub (pinned to f5988cc097)

Solutions

  1. Normalize before constructing: Angle(deg % 360).
  2. Convert types at the boundary: Angle(float(raw)) for string inputs.
  3. Be aware both bounds are inclusive — 360 is accepted, so normalize to [0, 360] not [0, 360).

Example fix

# before
import math
Angle(math.degrees(theta))  # theta > 2*pi gives degrees > 360

# after
Angle(math.degrees(theta) % 360)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(deg, (int, float)) or isinstance(deg, bool):
    deg = float(deg)
if not 0 <= deg <= 360:
    deg = deg % 360
Angle(deg)

Type guard

def is_valid_angle_deg(v: object) -> bool:
    return (
        isinstance(v, (int, float))
        and not isinstance(v, bool)
        and 0 <= v <= 360
    )

Try / catch

try:
    a = Angle(deg)
except TypeError as exc:
    if 'between 0 and 360' in str(exc):
        a = Angle(deg % 360)
    else:
        raise

Prevention

When it happens

Trigger: Constructing Angle(361), Angle(-0.5), or Angle('90'). Angle(0) and Angle(360) are both valid. The doctests show Angle(361) producing this exact TypeError.

Common situations: Converting angles from radians via math.degrees without normalizing (theta > 2*pi gives degrees > 360), compass headings that arrive above 360 after adding offsets, or string values from UI/config.

Related errors


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