Skip to content

Problem to delete pages on PDF #4790

Closed
Closed

Description

@Dayof

Description of the bug

I tried to delete pages using delete_pages() but it seems to not have effect when calling tobytes().
I cannot use insert_pdf() to create a new document without the pages as well because of the problem below:
#3315

How to reproduce the bug

>>> import pymupdf
>>> with open("Marco_Aurelio_Meditaciones_02_pages.pdf", "rb") as f:
...     pdf_content = f.read()
... 
>>> file_copy = pymupdf.open("pdf", pdf_content)
>>> page_to_keep = 0
>>> pages_to_delete = [i for i in range(len(file_copy)) if i != page_to_keep]
>>> file_copy.delete_pages(pages_to_delete)
>>> print(f"After deletion: {len(file_copy)} pages")
After deletion: 1 pages
>>> result_bytes = file_copy.tobytes()
>>> result_doc = pymupdf.open("pdf", result_bytes)
>>> print(f"Result document has {len(result_doc)} pages")
Result document has 2 pages

This is the document:
Marco_Aurelio_Meditaciones_02_pages.pdf

PyMuPDF version

1.26.3

Operating system

Linux

Python version

3.11

Activity

  1. JorjMcKie commented on Nov 14, 2025

    @JorjMcKie
    Collaborator

    This problem has nothing to do with whether the PDF is in memory or not.
    Even when the PDF is opened from disk and other page deletion forms are used, e.g. del doc[1] will not work.
    ... Investigating ...

  2. julian-smith-artifex-com commented on Feb 5, 2026

    @julian-smith-artifex-com
    Collaborator

    The problem here is that the document is broken, so the save() causes the document to be repaired, which in this case results in the the deletion of page 1 being lost.

    Unfortunately this is a general problem - it's not possible to guarantee that changes are preserved when repairing a faulty document.

    Note that checking whether a document is faulty and needs repairing is a very slow operation, requiring the entire document to be analysed. So it's not practical to do so by default for all documents.

    We're looking at providing some limited assistance for this sort of thing, but ultimately faulty documents cannot be reliably handled without large overheads.

  3. JorjMcKie commented on Feb 5, 2026

    @JorjMcKie
    Collaborator

    Just to underpin the comment of @julian-smith-artifex-com , here is a script that exhibits what is going on with this broken file.

    import pymupdf
    
    doc = pymupdf.open("Marco_Aurelio_Meditaciones_02_pages.pdf")
    print(f"'{doc.is_repaired=}' on open")
    page_to_keep = 0
    pages_to_delete = [i for i in range(len(doc)) if i != page_to_keep]
    print(f"{pages_to_delete=}")
    doc.delete_pages(pages_to_delete)
    print(f"'{doc.is_repaired=}' after deletion")
    print(f"After deletion: {len(doc)} pages")
    doc.ez_save("x.pdf", clean=True)
    print(f"'{doc.is_repaired=}' after save")
    # result_bytes = doc.tobytes(garbage=3)
    result_doc = pymupdf.open("x.pdf")
    print(f"'{result_doc.is_repaired=}' after open of saved file")
    print(f"Result document has {len(result_doc)} pages")

    Here is the output when executing the script:

    py test0.py
    
    'doc.is_repaired=False' on open
    pages_to_delete=[1]
    'doc.is_repaired=False' after deletion
    After deletion: 1 pages
    'doc.is_repaired=True' after save   # <=== !
    'result_doc.is_repaired=False' after open of saved file
    Result document has 2 pages
    

    See the commented line: When saving the file, MuPDF has detected errors and initiated a repair. This repair has reverted the changes previously made (page deletion in this case).

    So, the problem is detectable in principle, and the only "economic" way out is to repeat the page deletion with the repaired copy ("x.pdf") of the file.

  4. julian-smith-artifex-com commented on Feb 5, 2026

    @julian-smith-artifex-com
    Collaborator

    We've just added a couple of new things to git:

    • New method Document.repair(), which repairs PDF documents if necessary. Will be slow.
    • New arg raise_on_repair for Document.save(). If set to true, .save() will raise an exception if it had to repair the document.

    This is probably as much as we can do to help the situation - setting raise_on_repair=True when saving will make it clear if the saved document might lose some or all of the changes that have been made to it.

    For example you could use it to repeat the operations with a manual repair:

    def modify_document(document):
        document.delete_pages(1)
    
    ok = True
    with pymupdf.open(path) as document:
        modify_document(document)
        try:
            document.save(path2, raise_on_repair=1)
        except Exception:
            ok = False
    if not ok:
        with pymupdf.open(path) as document:
            document.repair()
            modify_document(document)
            document.save(path2)
    

    [We might define a new exception type to avoid getting triggered by unrelated errors.]

  5. julian-smith-artifex-com commented on Feb 11, 2026

    @julian-smith-artifex-com
    Collaborator

    Fixed in PyMuPDF-1.27.1.

  6. Dayof commented on Feb 11, 2026

    @Dayof
    Author

    Thanks @JorjMcKie and @julian-smith-artifex-com for the investigation and the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions