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
- Normalize and snap the angle first: snapped = round(angle / 90) * 90 % 360, then pass snapped.
- Check angle in (0, 90, 180, 270) before calling and log/skip if not, so one bad page does not abort a batch conversion.
- 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
- Normalize every rotation angle with round(a / 90) * 90 % 360 before geometry ops.
- Treat orientation as an enum of four classes, not a continuous value, at API boundaries.
- Log and skip bad angles per item so one bad detection does not kill a batch conversion.
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
- invalid tesseract document orientation {orientation}, expect
- Cannot convert Box Note with hash {self.document_hash}: no '
- Cannot convert doc with {self.document_hash} because the bac
- Archive exceeds maximum member count limit of {self.options.
- Invalid base_path format: '{base_path}'
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/adc2f89d2443ad29.
Report an issue: GitHub.