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
- 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).
- 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).
- 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
- Snap all detected angles to round(angle / 90) * 90 % 360 before passing them in.
- Only feed orientation strings produced by Tesseract's own orientation script output.
- In batch pipelines, wrap the call per page and continue on failure instead of aborting the document.
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
- Invalid Tesseract language identifier: {lang!r}. Language id
- Invalid Tesseract data path: contains null byte.
- Invalid Tesseract command: contains null byte.
- Invalid filename: contains null byte.
- Cannot specify both ocr_preset and ocr_custom_config.
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/74571f1d12e7f458.
Report an issue: GitHub.