calesthio/OpenMontage · error · RuntimeError
stage drawer did not open
Error message
stage drawer did not open
What it means
Raised by scripts/backlot_visual_eval.py's interaction smoke when clicking the first .stage element opens a .drawer but its rendered text does not contain the word 'research'. The check verifies the stage drawer actually populated with stage content (the expected first stage being research-related), not merely that a drawer element appeared — so this fires when the drawer opens empty, shows an error/loading state, or displays the wrong stage's data.
Source
Thrown at scripts/backlot_visual_eval.py:180
report.append(result)
return report
def run_interactions(capture_dir: Path) -> dict[str, Any]:
"""Run browser interaction smoke through Python Playwright."""
from playwright.sync_api import sync_playwright
screenshot = capture_dir / "interaction-smoke.png"
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=True)
page = browser.new_page(viewport={"width": 1560, "height": 1000})
page.goto(f"http://127.0.0.1:{PORT}/p/the-last-lighthouse?static=1")
page.wait_for_selector(".stage")
page.locator(".stage").first.click()
page.wait_for_selector(".drawer")
drawer_text = page.locator(".drawer").inner_text()
if "research" not in drawer_text:
raise RuntimeError("stage drawer did not open")
page.locator(".script-card").first.click()
page.wait_for_selector(".modal-bg.open")
page.keyboard.press("Escape")
page.wait_for_function("() => !document.querySelector('.modal-bg')?.classList.contains('open')")
if page.locator(".takes").count() < 1:
raise RuntimeError("takes drawer not present on staged takes scene")
replay_button = page.locator(".rp-btn", has_text="REPLAY RUN")
if replay_button.count():
replay_button.first.click()
page.wait_for_selector('input[type="range"]')
page.locator('input[type="range"]').fill("500")
page.screenshot(path=str(screenshot), full_page=True)
browser.close()
return {"status": "passed", "screenshot": str(capture_dir / "interaction-smoke.png")}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Open http://127.0.0.1:{PORT}/p/the-last-lighthouse?static=1 manually, click a stage, and inspect what the drawer actually shows.
- If content is correct but the wording changed, update the expected substring in scripts/backlot_visual_eval.py.
- If the drawer is empty/loading, fix the underlying data load or add a wait for the content to populate before asserting.
Example fix
# before
if "research" not in drawer_text:
raise RuntimeError("stage drawer did not open")
# after (match current content + wait for population)
page.wait_for_function("() => document.querySelector('.drawer')?.innerText.trim().length > 0")
if "research" not in page.locator(".drawer").inner_text().lower():
raise RuntimeError("stage drawer did not open") Defensive patterns
Strategy: validation
Validate before calling
drawer_text = page.locator(".drawer").inner_text()
expected_stage = "research"
if expected_stage not in drawer_text.lower():
# drawer opened but content missing/wrong — dump actual text for diagnosis
raise AssertionError(f"drawer content unexpected: {drawer_text[:200]!r}") Try / catch
try:
run_interaction_smoke()
except RuntimeError as e:
if "stage drawer did not open" in str(e):
# inspect capture_dir/interaction-smoke.png (if reached) or run manually to see actual drawer state
log.error("Drawer content check failed — open the page manually and inspect .drawer text")
raise Prevention
- Keep smoke assertions tied to stable content anchors, and update them in the same PR that changes UI copy.
- Wait for drawer text to be non-empty before substring assertions.
- On failure, reproduce manually in a headed browser before changing the check.
When it happens
Trigger: Running the interaction smoke against the Backlot static page (?static=1) when stage data fails to load, the drawer component renders before data arrives, a refactor renamed stage content so 'research' no longer appears, or the clicked .stage resolves to a different stage than expected.
Common situations: Frontend refactor changing stage labels or drawer content structure; fixture data for 'the-last-lighthouse' missing or renamed; race where the smoke asserts text before async content renders.
Related errors
- takes drawer not present on staged takes scene
- Refusing paid Atlas calls without --allow-paid
- Playwright is required to render preview MP4
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/0c8c038d3341a56e.
Report an issue: GitHub.