docling-project/docling · error · ValueError

invalid tesseract document orientation {orientation}, expect

Error message

invalid tesseract document orientation {orientation}, expected orientation: {sorted(CLIPPED_ORIENTATIONS)}

What it means

Raised by parse_tesseract_orientation() in docling/utils/ocr_utils.py when the orientation string reported for a page is not one of the four Tesseract orientation classes (0, 90, 180, 270 clockwise). The function converts Tesseract's clockwise bounding-rectangle angle into Docling's counterclockwise [0,360[ convention, so it only accepts those four discrete values. Any other numeric value is rejected before conversion.

Source

Thrown at docling/utils/ocr_utils.py:29

    if script == "Katakana" or script == "Hiragana":
        script = "Japanese"
    elif script == "Han":
        script = "HanS"
    elif script == "Korean":
        script = "Hangul"
    return script


def parse_tesseract_orientation(orientation: str) -> int:
    # Tesseract orientation is [0, 90, 180, 270] clockwise, bounding rectangle angles
    # are [0, 360[ counterclockwise
    parsed = int(orientation)
    if parsed not in CLIPPED_ORIENTATIONS:
        msg = (
            f"invalid tesseract document orientation {orientation}, "
            f"expected orientation: {sorted(CLIPPED_ORIENTATIONS)}"
        )
        raise ValueError(msg)
    parsed = -parsed
    parsed %= 360
    return parsed


def tesseract_box_to_bounding_rectangle(
    bbox: BoundingBox,
    *,
    original_offset: Optional[BoundingBox] = None,
    scale: float,
    orientation: int,
    im_size: Tuple[int, int],
) -> BoundingRectangle:
    # box is in the top, left, height, width format, top left coordinates
    rect = rotate_bounding_box(bbox, angle=orientation, im_size=im_size)
    rect = BoundingRectangle(
        r_x0=rect.r_x0 / scale,
        r_y0=rect.r_y0 / scale,

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Snap the detected angle to the nearest multiple of 90 and normalize with angle % 360 before calling the function (e.g. round(angle / 90) * 90 % 360).
  2. Verify the value originates from Tesseract's orientation script output and is not corrupted by upstream parsing (check for leading/trailing characters or sign flips).
  3. If you genuinely need arbitrary-angle deskew, handle rotation upstream of OCR rather than through this function, which only supports document-level 90-degree orientations.

Example fix

# before
angle = detect_rotation(image)  # e.g. 45.0
parsed = parse_tesseract_orientation(str(angle))  # ValueError

# after
angle = detect_rotation(image)
snapped = round(angle / 90) * 90 % 360  # nearest of 0/90/180/270
parsed = parse_tesseract_orientation(str(int(snapped)))
Defensive patterns

Strategy: validation

Validate before calling

CLIPPED = {0, 90, 180, 270}
angle = round(detected_angle / 90) * 90 % 360
if int(angle) not in CLIPPED:
    raise ValueError(f"unsupported angle {detected_angle}; snapping failed")
parsed = parse_tesseract_orientation(str(int(angle)))

Type guard

def is_valid_tesseract_orientation(value: str) -> bool:
    try:
        return int(value) in {0, 90, 180, 270}
    except ValueError:
        return False

Try / catch

try:
    parsed = parse_tesseract_orientation(orientation_str)
except ValueError as exc:
    logger.warning("skipping page with bad orientation %r: %s", orientation_str, exc)
    parsed = 0  # or skip the page

Prevention

When it happens

Trigger: Calling parse_tesseract_orientation(orientation) with a string that parses to an int but is not in {0, 90, 180, 270}, e.g. "45", "360", "-90", or a value coming from a custom/patched Tesseract orientation output or an OCR engine adapter that emits arbitrary angles.

Common situations: Feeding orientation values from a non-Tesseract OCR pipeline or precomputed metadata into Docling's Tesseract OCR path; upgrading or patching Tesseract so its orientation output format changes; manually computing orientation angles (e.g. via image rotation detection) and passing fractional or non-orthogonal angles.

Related errors


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