MadsLorentzen/ai-job-search · error · VerificationError
text layer is missing required text: {required!r} (extractor
Error message
text layer is missing required text: {required!r} (extractor: {extractor}) What it means
Raised when one of the required_text strings cannot be found in the PDF's normalized text layer. Both the extracted text and the required snippet are whitespace-normalized, so the failure means the wording genuinely differs, not merely line-break formatting.
Source
Thrown at tools/verify_pdf.py:125
raise VerificationError(
f"could not write --dump-text to {dump_path}: {exc}"
) from exc
if expected_pages is not None and actual_pages != expected_pages:
raise VerificationError(
f"expected {expected_pages} page(s), found {actual_pages} (extractor: {extractor})"
)
normalized = normalize_text(extracted_text)
if len(normalized) < min_chars:
raise VerificationError(
f"text layer has {len(normalized)} character(s); expected at least {min_chars} "
f"(extractor: {extractor})"
)
for required in required_text:
if normalize_text(required) not in normalized:
raise VerificationError(
f"text layer is missing required text: {required!r} (extractor: {extractor})"
)
return extractor, extracted_text, actual_pages
def build_parser():
parser = argparse.ArgumentParser(
description="Verify a PDF's page count and ATS-readable text layer."
)
parser.add_argument("pdf", type=Path, help="PDF file to verify")
parser.add_argument("--pages", type=int, help="required exact page count")
parser.add_argument(
"--min-chars",
type=int,
default=1,
help="minimum non-whitespace text-layer characters (default: 1)",
)
parser.add_argument(View on GitHub (pinned to 79cd383e58)
Solutions
- Dump the extracted text (use dump_text/--dump-text or pdftotext) and search for the closest actual wording; update required_text to match
- Fix the generator so the expected literal actually appears in the text layer
- Normalize unicode on your side (e.g. unicodedata.normalize('NFKC') on both sides) or choose required snippets without ligatures/smart punctuation
- If the phrase only exists as an image, add OCR or drop that required_text entry
Example fix
# before
verify_pdf(pdf, required_text=('Total: 1,234.50',))
# after — match actual localized formatting in the text layer
verify_pdf(pdf, required_text=('Total:', '1.234,50')) Defensive patterns
Strategy: validation
Validate before calling
import subprocess
norm = lambda s: ' '.join(s.split())
text = norm(subprocess.run(['pdftotext', str(pdf), '-'], capture_output=True, text=True).stdout)
missing = [r for r in required if norm(r) not in text]
assert not missing, f'will fail verification: {missing}' Try / catch
try:
verify_pdf(pdf, required_text=required)
except VerificationError as e:
if 'missing required text' in str(e):
dump_and_diff(pdf, required) # inspect actual wording, then adjust Prevention
- Keep required_text snippets short and punctuation-free to dodge unicode differences
- Apply NFKC normalization to snippets and expected text on your side
- Use dump_text to review exactly what the extractor sees before adding assertions
When it happens
Trigger: Calling verify_pdf(path, required_text=('Invoice Total',)) where that phrase (after whitespace collapsing) does not appear: dynamic content differs from the expected literal, unicode/ligature differences, hyphenation splitting words, or the phrase living in an image rather than the text layer.
Common situations: Template wording changed but the verification literal was not updated; localized date/currency formatting differences; ligatures (fi/fl) or smart quotes in extracted text; required text rendered inside an embedded image or SVG.
Related errors
- pdfinfo output did not contain a page count
- PDF does not exist: {pdf_path}
- expected {expected_pages} page(s), found {actual_pages} (ext
- text layer has {len(normalized)} character(s); expected at l
- could not write --dump-text to {dump_path}: {exc}
AI-assisted analysis of MadsLorentzen/ai-job-search@79cd383e58 (2026-08-27).
Data as JSON: /api/errors/108a2dc4f29b01bd.
Report an issue: GitHub.