# What Happens When You Process an Image-Only PDF in Book-to-Skill

> Discover what happens when processing an image-only PDF in Book-to-Skill. Learn how it aborts extraction and raises an error, preventing silent failures.

- Repository: [Virgilio Junior/book-to-skill](https://github.com/virgiliojr94/book-to-skill)
- Tags: how-to-guide
- Published: 2026-08-31

---

**Book-to-Skill immediately aborts the extraction pipeline and raises an explicit `ExtractionError` with instructions to OCR the document first, preventing silent failures on scanned image files.**

When processing documents in the [virgiliojr94/book-to-skill](https://github.com/virgiliojr94/book-to-skill) repository, the extraction system includes built-in safeguards against image-only PDFs. Unlike tools that return empty strings or garbled output on scanned documents, Book-to-Skill detects these files early and provides actionable guidance for preprocessing.

## Fast Pre-Flight Detection with `looks_image_only`

Before attempting full text extraction, Book-to-Skill runs a lightweight validation check. The `looks_image_only` function, defined at line 93 in [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py), executes `pdftotext` on the first five pages of the PDF by default.

If `pdftotext` returns no extractable text, the function returns `True`, flagging the document as image-only:

```python
from book_to_skill.parsers.pdf import looks_image_only

pdf_path = "my_scanned_book.pdf"
if looks_image_only(pdf_path):
    print("This PDF is image-only – run OCR before extraction.")
else:
    print("Text extraction can proceed.")

```

This early detection prevents wasted processing time on files that cannot yield selectable text.

## The Extraction Abort Mechanism

When the main extraction logic calls `extract_single_file` (see the PDF branch around line 50 in [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py)), it inspects the `looks_image_only` result before proceeding. If the check returns `True`, the pipeline raises `ExtractionError` defined in [`book_to_skill/exceptions.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/exceptions.py):

```python
if looks_image_only(input_str):
    raise ExtractionError(
        f"{input_path.name} looks like a scanned (image-only) PDF: its first pages "
        "contain no extractable text, only images.\n"
        "Run OCR on it first, then retry:\n"
        "  ocrmypdf input.pdf output.pdf"
    )

```

The exception bubbles up to the top-level loop in `main()`, which logs a warning and skips the file entirely. This ensures image-only PDFs never reach the downstream skill generation logic.

## Command-Line Experience

When using the CLI tool, users receive immediate, actionable feedback. Instead of cryptic failures or empty output files, the terminal displays:

```bash
$ book-to-skill scanned_book.pdf
book-to-skill · turns a document into a structured agent skill

Extracting PDF: /home/user/scanned_book.pdf
  [warn] scanned_book.pdf looks like a scanned (image-only) PDF: its first pages contain no extractable text, only images.
  Run OCR on it first, then retry:
    ocrmypdf scanned_book.pdf scanned_book_ocr.pdf

```

This clear messaging eliminates guesswork about why extraction failed.

## Fixing Image-Only PDFs with OCR

To process a scanned document through Book-to-Skill, you must first apply Optical Character Recognition (OCR). The error message explicitly suggests using `ocrmypdf`, a command-line tool that adds a text layer to image-based PDFs:

```bash
ocrmypdf input.pdf output.pdf

```

After OCR processing, the PDF contains selectable text, allowing `looks_image_only` to return `False` and permitting normal extraction to proceed.

## Programmatic Error Handling

When integrating Book-to-Skill into larger applications, catch `ExtractionError` to handle image-only PDFs gracefully:

```python
from book_to_skill.utils import extract_single_file
from book_to_skill.exceptions import ExtractionError
from pathlib import Path

try:
    result = extract_single_file(
        Path("scanned_book.pdf"), 
        extraction_mode="text", 
        install_mode="ask"
    )
except ExtractionError as exc:
    print(f"Extraction failed: {exc}")
    # Implement logic to trigger OCR or notify users

```

This pattern allows automated workflows to route unscanned documents through preprocessing pipelines.

## Key Source Files

| File | Role |
|------|------|
| [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py) | Implements `looks_image_only`, the PDF-only detection logic, and the various PDF extraction back-ends. |
| [`book_to_skill/utils.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/utils.py) | Calls `looks_image_only` before attempting extraction; raises `ExtractionError` on image-only PDFs. |
| [`tests/test_book_to_skill.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/tests/test_book_to_skill.py) | Unit test confirming that `looks_image_only` correctly identifies image-only PDFs and that the extractor aborts with a helpful error (around line 1965). |
| [`book_to_skill/exceptions.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/exceptions.py) | Defines `ExtractionError`, the exception type used for the early abort. |

## Summary

- **Early Detection**: The `looks_image_only` function in [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py) checks the first five pages using `pdftotext` to identify scanned documents.
- **Explicit Failure**: Instead of returning empty content, Book-to-Skill raises `ExtractionError` with specific OCR instructions.
- **Actionable Guidance**: Error messages include the exact `ocrmypdf` command needed to preprocess the file.
- **Test Coverage**: The behavior is validated in [`tests/test_book_to_skill.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/tests/test_book_to_skill.py) around line 1965, ensuring reliable detection of image-only PDFs.

## Frequently Asked Questions

### Can Book-to-Skill extract text from scanned image-only PDFs?

No. Book-to-Skill explicitly rejects image-only PDFs during the pre-flight check. The `looks_image_only` function detects when a PDF contains no selectable text and aborts processing before extraction begins. You must first run OCR tools like `ocrmypdf` to add a text layer to the document.

### What error message appears when processing an image-only PDF?

Book-to-Skill raises an `ExtractionError` with the message: `[filename] looks like a scanned (image-only) PDF: its first pages contain no extractable text, only images. Run OCR on it first, then retry: ocrmypdf input.pdf output.pdf`. This appears in both CLI output and exception traces.

### How does Book-to-Skill detect if a PDF is image-only?

The detection happens in [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py) via the `looks_image_only` function. It runs `pdftotext` on the first five pages of the PDF. If the command returns no text content, the function returns `True`, triggering the extraction abort in `extract_single_file`.

### Which file handles the image-only PDF error in Book-to-Skill?

The primary detection logic resides in [`book_to_skill/parsers/pdf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/parsers/pdf.py), while [`book_to_skill/utils.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/utils.py) contains the `extract_single_file` function that actually raises the `ExtractionError`. The exception class itself is defined in [`book_to_skill/exceptions.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/book_to_skill/exceptions.py).