`find_pdf_path_for_review` raises UnboundLocalError when no reflection PDF exists, crashing the run at the final review step

Author: GoldenmonstewCreated Jun 12, 2026Updated Jul 7, 2026

Related issues: no existing issue found (searched: UnboundLocalError, review, pdf, find_pdf). #16 ("How can i get the PDF?") shows missing-PDF symptoms but no traceback — not a duplicate.

Summary

find_pdf_path_for_review only assigns its return variable inside the if reflection_pdfs: branch. If the idea directory contains no PDF at all — or only PDFs without "reflection" in the name — the function hits return pdf_path with pdf_path unbound and raises UnboundLocalError. Because the call site sits between the writeup and review steps and is not guarded, a run that already completed ideation, the full tree search, plotting, and (a failed) writeup dies with rc=1 at the very last step instead of gracefully skipping review.

Where

launch_scientist_bfts.py:140–164 at current main (96bd516):

python
def find_pdf_path_for_review(idea_dir):
    pdf_files = [f for f in os.listdir(idea_dir) if f.endswith(".pdf")]
    reflection_pdfs = [f for f in pdf_files if "reflection" in f]
    if reflection_pdfs:
        # First check if there's a final version
        final_pdfs = [f for f in reflection_pdfs if "final" in f.lower()]
        if final_pdfs:
            pdf_path = osp.join(idea_dir, final_pdfs[0])
        else:
            ...
    return pdf_path        # <-- unbound when reflection_pdfs is empty

Call site, lines 304–308:

python
    if not args.skip_review and not args.skip_writeup:
        # Perform paper review if the paper exists
        pdf_path = find_pdf_path_for_review(idea_dir)
        if os.path.exists(pdf_path):
            print("Paper found at: ", pdf_path)

The os.path.exists(pdf_path) guard shows the no-PDF case was meant to be handled gracefully — control just never reaches it.

Impact

  • Any run whose writeup produced no PDF (see the related writeup success-flag issue: even "successful" writeups can end with no reflection-named PDF after retries) exits with a traceback and rc=1 in the review step, after many hours of completed experiment compute.
  • Because the crash happens before the process-cleanup section further down the script (line 321+), child experiment processes can also be left behind.
  • Observed in batch reproduction: runs with finished experiments + writeup attempts classified as hard failures by the outer scheduler purely because of this final-step crash; the artifacts were actually fine up to the writeup.

Repro sketch

  1. Run launch_scientist_bfts.py without --skip_review/--skip_writeup and with any condition that leaves no *reflection*.pdf in the idea directory (simplest: temporarily make perform_writeup fail, or delete the PDFs before the review step).
  2. Observe:
UnboundLocalError: cannot access local variable 'pdf_path' where it is not associated with a value

and the whole launch exiting rc=1.

Suggested fix (minimal)

Initialize the variable and let the existing guard do its job:

python
def find_pdf_path_for_review(idea_dir):
    pdf_path = None
    ...
    return pdf_path

and at the call site:

python
        pdf_path = find_pdf_path_for_review(idea_dir)
        if pdf_path and os.path.exists(pdf_path):

(Optionally also fall back to non-reflection PDFs — pdf_files is already computed but unused in the no-reflection case — so a paper produced under the base name can still be reviewed.)

Source: SakanaAI/AI-Scientist-v2