docling-project/docling · error · ValueError

invalid orientation {angle}, expected values in: {sorted(CLI

Error message

invalid orientation {angle}, expected values in: {sorted(CLIPPED_ORIENTATIONS)}

What it means

Raised in docling/utils/orientation.py when applying an orientation/rotation angle to build a BoundingRectangle and the angle is not one of the clipped orientations {0, 90, 180, 270}. The function has explicit branches that permute the rectangle's corner coordinates for each supported 90-degree rotation; any other angle falls into the else branch and raises ValueError because no geometry is defined for it.

Source

Thrown at docling/utils/orientation.py:53

        r_x2 = r_x1
        r_y2 = r_y1 + height
        r_x3 = r_x0
        r_y3 = r_y2
    elif angle == 270:
        r_x0 = im_h - (top + height)
        r_y0 = left
        r_x1 = r_x0
        r_y1 = r_y0 + width
        r_x2 = r_x1 + height
        r_y2 = r_y1
        r_x3 = r_x2
        r_y3 = r_y0
    else:
        msg = (
            f"invalid orientation {angle}, expected values in:"
            f" {sorted(CLIPPED_ORIENTATIONS)}"
        )
        raise ValueError(msg)
    rectangle = BoundingRectangle(
        r_x0=r_x0,
        r_y0=r_y0,
        r_x1=r_x1,
        r_y1=r_y1,
        r_x2=r_x2,
        r_y2=r_y2,
        r_x3=r_x3,
        r_y3=r_y3,
        coord_origin=CoordOrigin.TOPLEFT,
    )
    return rectangle

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Normalize and snap the angle first: snapped = round(angle / 90) * 90 % 360, then pass snapped.
  2. Check angle in (0, 90, 180, 270) before calling and log/skip if not, so one bad page does not abort a batch conversion.
  3. Trace where the angle comes from — orientation classifiers should already emit only the four valid classes; if not, fix the upstream producer.

Example fix

# before
rect = apply_orientation(rect, angle=detect_angle(page))  # ValueError if 45.0

# after
angle = round(detect_angle(page) / 90) * 90 % 360
if angle in (0, 90, 180, 270):
    rect = apply_orientation(rect, angle=angle)
Defensive patterns

Strategy: validation

Validate before calling

angle = round(angle / 90) * 90 % 360
if angle not in (0, 90, 180, 270):
    raise ValueError(f"angle {angle} not supported for rectangle rotation")
rect = apply_orientation(rect, angle=angle)

Type guard

def is_clipped_orientation(angle: int | float) -> bool:
    return angle in (0, 90, 180, 270)

Try / catch

try:
    rect = apply_orientation(rect, angle)
except ValueError:
    logger.warning("dropping unsupported orientation %s for item", angle)
    return rect  # keep unrotated geometry

Prevention

When it happens

Trigger: Calling the orientation application function in orientation.py (e.g. when rotating bounding rectangles for page orientation corrections) with an angle such as 45, 360, -90, or 90.5 — anything outside CLIPPED_ORIENTATIONS.

Common situations: Passing raw rotation-detection output (which may be arbitrary degrees) directly into rectangle rotation; normalizing angles incorrectly (e.g. forgetting % 360 so 360 or negative values slip through); mixing clockwise/counterclockwise conventions so 270 vs -90 mismatch occurs.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/adc2f89d2443ad29. Report an issue: GitHub.