Skip to content

Skip exhibit pages with no valid files instead of crashing - #1098

Open
rajeswari1301 wants to merge 5 commits into
mainfrom
skip-empty-exhibit-pages
Open

Skip exhibit pages with no valid files instead of crashing#1098
rajeswari1301 wants to merge 5 commits into
mainfrom
skip-empty-exhibit-pages

Conversation

@rajeswari1301

@rajeswari1301 rajeswari1301 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Fixes a bug where a user's document download kept failing. when every page for one file failed to load, it tried to build a PDF out of nothing and crashed the whole download instead of just skipping that file.

Three small fixes at each level where this could happen:

  1. ALExhibit.as_pdf() - filters out missing or broken pages before building that exhibit's PDF. If nothing valid is left, logs it and returns None instead of crashing.
  2. ALExhibitList.as_pdf() - now skips any exhibit that came back empty from step 1, and returns None if every exhibit ends up empty.
  3. ALExhibitDocument.as_pdf() - handles step 2 returning None, so it doesn't crash trying to combine it with the table of contents.

None of these results get cached, so if something comes back on a retry (like it did in our actual case, which was a one-time blip), it's not stuck as skipped for the rest of the session.

Still need to test this against something close to the actual broken case before merging.

@rajeswari1301
rajeswari1301 force-pushed the skip-empty-exhibit-pages branch from 9a98bf5 to 0f68097 Compare August 25, 2026 22:28
@rajeswari1301
rajeswari1301 force-pushed the skip-empty-exhibit-pages branch from 415b3d5 to 9fa8ea6 Compare August 25, 2026 23:10

@nonprofittechy nonprofittechy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good - wait to merge until you do your tests.

Main question is what happens if a None is able to escape--is it safe all the way up? I would try some adversarial bundles to test this.

Also: I see why this happened - we probably patched ALDocument but not ALExhibitList. Are there other descendants of ALDocument that we need to repair/guard in the same way? It would make sense to do those at the same time.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents exhibit PDF generation from crashing when an exhibit ends up with zero loadable pages by filtering invalid pages, skipping empty exhibits, and propagating “no output” (None) up to the top-level exhibit-document assembly.

Changes:

  • ALExhibit.as_pdf(): filters out missing/broken pages before concatenation; returns None when no valid pages remain.
  • ALExhibitList.as_pdf(): skips exhibits that return None; returns None when all exhibits are empty.
  • ALExhibitDocument.as_pdf(): handles an empty exhibit list PDF result to avoid crashing when combining with the table of contents; return types updated to Optional[DAFile].
Suppressed comments (3)

docassemble/AssemblyLine/al_document.py:3118

  • ALExhibitList.as_pdf() now returns Optional[DAFile], but the docstring doesn't mention that it can return None when there are no valid exhibits to include. Please document the None case explicitly.
        """
        Compiles all exhibits in the list into a single PDF.

docassemble/AssemblyLine/al_document.py:3476

  • as_docx() delegates to as_pdf(), which can now return None. The docstring should mention the None possibility so callers don't assume a DAFile is always returned.
        """
        Despite the name, renders the document as a PDF. Provided for signature compatibility.

docassemble/AssemblyLine/al_document.py:3415

  • ALExhibitDocument.as_pdf() now returns Optional[DAFile], but the docstring doesn't mention that it can return None (e.g., when there are no exhibits and no table of contents to return). Please document the None case.
        """
        Render the document as a PDF.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docassemble/AssemblyLine/al_document.py
Comment thread docassemble/AssemblyLine/al_document.py Outdated
Comment thread docassemble/AssemblyLine/al_document.py
@nonprofittechy

Copy link
Copy Markdown
Member

Copilot's findings all also look worth addressing prior to merging, esp. updating the docstring. ideally we could also scan for now-unsafe use in our other repos

@rajeswari1301

Copy link
Copy Markdown
Contributor Author

This looks good - wait to merge until you do your tests.

Main question is what happens if a None is able to escape--is it safe all the way up? I would try some adversarial bundles to test this.

Also: I see why this happened - we probably patched ALDocument but not ALExhibitList. Are there other descendants of ALDocument that we need to repair/guard in the same way? It would make sense to do those at the same time.

Good question, no not fully yet. Found a few more spots in ALDocumentBundle that assume as_pdf/as_docx never returns None, as_zip, as_pdf_list, as_docx_list, get_cacheable_documents, and a couple branches inside as_pdf itself. I'll add those to this PR too

Extends the same fix to the rest of ALDocumentBundle: as_pdf, as_zip, as_pdf_list, as_docx_list, as_docx, get_cacheable_documents, download_html, send_email, and str, all of which had the same gap as the exhibit classes.

Also added a safety check to size_in_bytes, so a single bad page won't break the whole size calculation anymore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants