`find_pdf_path_for_review` raises UnboundLocalError when no reflection PDF exists, crashing the run at the final review step
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):
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 emptyCall site, lines 304–308:
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
- Run
launch_scientist_bfts.pywithout--skip_review/--skip_writeupand with any condition that leaves no*reflection*.pdfin the idea directory (simplest: temporarily makeperform_writeupfail, or delete the PDFs before the review step). - Observe:
UnboundLocalError: cannot access local variable 'pdf_path' where it is not associated with a valueand the whole launch exiting rc=1.
Suggested fix (minimal)
Initialize the variable and let the existing guard do its job:
def find_pdf_path_for_review(idea_dir):
pdf_path = None
...
return pdf_pathand at the call site:
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