{"record":{"id":"c3fc1bcb0c2ba40f","repo":"ocrmypdf/OCRmyPDF","slug":"page-already-has-text-aborting-use-force-ocr","errorCode":null,"errorMessage":"page already has text! - aborting (use --force-ocr or --mode force to force OCR; see also help for --skip-text, --redo-ocr, and --mode)","messagePattern":"page already has text! - aborting \\(use --force-ocr or --mode force to force OCR; see also help for --skip-text, --redo-ocr, and --mode\\)","errorType":"error_code","errorClass":"PriorOcrFoundError","httpStatus":null,"severity":"error","filePath":"src/ocrmypdf/_pipeline.py","lineNumber":354,"sourceCode":"\ndef is_ocr_required(page_context: PageContext) -> bool:\n    \"\"\"Check if the page needs to be OCR'd.\"\"\"\n    pageinfo = page_context.pageinfo\n    options = page_context.options\n\n    if options.mode == ProcessingMode.strip_text:\n        # Strip mode removes the OCR text layer in place; it never rasterizes\n        # or runs OCR. The stripping happens in OcrGrafter.graft_page.\n        return False\n\n    ocr_required = True\n\n    if options.pages and pageinfo.pageno not in options.pages:\n        log.debug(f\"skipped {pageinfo.pageno} as requested by --pages {options.pages}\")\n        ocr_required = False\n    elif pageinfo.has_text:\n        if options.mode == ProcessingMode.default:\n            raise PriorOcrFoundError(\n                \"page already has text! - aborting (use --force-ocr or --mode force \"\n                \"to force OCR; see also help for --skip-text, --redo-ocr, and --mode)\"\n            )\n        elif options.mode == ProcessingMode.force:\n            log.info(\"page already has text! - rasterizing text and running OCR anyway\")\n            ocr_required = True\n        elif options.mode == ProcessingMode.redo:\n            if pageinfo.has_corrupt_text:\n                log.warning(\n                    \"some text on this page cannot be mapped to characters: \"\n                    \"consider using --force-ocr (or --mode force) instead\"\n                )\n            else:\n                log.info(\"redoing OCR\")\n            ocr_required = True\n        elif options.mode == ProcessingMode.skip:\n            log.info(\"skipping all processing on this page\")\n            ocr_required = False","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/ocrmypdf/OCRmyPDF/blob/5074a0b0e109362422b768fd271ed84bf717c4ec/src/ocrmypdf/_pipeline.py#L336-L372","documentation":"Raised in default mode when a page already contains text, because OCRing over existing text produces degraded output. ocrmypdf refuses unless you explicitly choose a strategy (--force-ocr, --skip-text, or --redo-ocr).","triggerScenarios":"options.mode == ProcessingMode.default (no mode flag) and pageinfo.has_text is true for any page; raised per-page in is_ocr_required.","commonSituations":"Running ocrmypdf on a digitally-born or previously OCRed PDF without any mode flag.","solutions":["Use --redo-ocr if the existing text is an OCR layer you want replaced","Use --skip-text if you want text pages left alone","Use --force-ocr if you must rasterize and re-OCR everything (acknowledging quality loss)","Check the input: you may be processing the wrong (already-text) file"],"exampleFix":"# before\nocrmypdf scanned.pdf out.pdf  # Error: page already has text!\n# after\nocrmypdf --redo-ocr scanned.pdf out.pdf","handlingStrategy":"validation","validationCode":"import pikepdf\nwith pikepdf.open(src) as pdf:\n    has_text = any(page.extract_text() for page in pdf.pages())\nif has_text and mode is None:\n    mode = 'redo' if from_ocr else 'skip'","typeGuard":null,"tryCatchPattern":"catch ocrmypdf.PriorOcrFoundError and re-run with an explicit --mode chosen by the user","preventionTips":["Always pass an explicit mode flag (--redo-ocr/--skip-text/--force-ocr) for mixed corpora","Sample-check inputs for existing text layers in batch front-ends"],"tags":["ocr","ocrmypdf","text-layer","processing-mode"],"backgroundTag":"existing-text-layer-conflict","analyzedSha":"5074a0b0e109362422b768fd271ed84bf717c4ec","analyzedAt":"2026-08-27T11:57:38.523Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}