--- id: "b3dd54e4-b11b-42ea-b9d2-efa678043385" name: "Common Pitfalls" micro_summary: "Required reading: traps that break browser-harness commands" status: "in_progress" see_also: [] scope: "Traps that break browser-harness commands — document not defined, bash quote mismatches, variable collisions, stale sessions, swallowed output, and iframe context traps." --- ## Common pitfalls 1. **NameError: name 'document' is not defined** — `document` is only available inside `js()`, not in the Python wrapper. 2. **Bash syntax errors with `')`** — mismatched quotes cause bash to fail before the command even runs. 3. **Variable collisions** — `js()` accumulates state; use IIFE for multi-line code. 4. **Stale sessions** — use `ensure_real_tab()` if the tab is stale. 5. **No output from `js('...')`** — single-quoted JS sometimes swallows output; prefer double-quoted or triple-quoted. 6. **innerHTML bloat on React/Next.js** — `document.body.innerHTML` captures component definitions, compiled MDX, and scripts. Use `extract_text()` instead. 7. **iframe_target() doesn't change CDP execution context** — `iframe_target()` switches the visible frame but `js()` and `extract_text()` still execute in the parent page's CDP context. To extract iframe content, use parent-page JS: `document.querySelector("iframe")?.contentWindow?.document?.body?.innerHTML`. --- ### 2026-09-01 02:40 UTC ### 2026-08-31 — working fallback when wheel scroll dies: drive scrollTop via js() Heuristic to find the scrollable container: `e.scrollHeight > e.clientHeight + 200 && e.clientHeight > 300` — first matching div may be a side pane rather than the target list, so verify before bumping. To scroll an element into view before `click_at_xy`, compute the target directly: `card.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop`, then re-check the card's rect — a card above/below the viewport yields negative/out-of-range y and the coordinate click lands in dead space (observed: click at y=-60.125 silently did nothing; pane state unchanged). LinkedIn's classic `ul.scaffold-layout__list-container` selector was absent in the new UI; the list wrapper is a div with an obfuscated random-generated class. Structured card mining worked via `[data-job-id]` attribute collection (id + trimmed textContent per card). --- ### 2026-09-24 00:00 UTC ### 2026-09-23 — fill_input() can fail to commit on some framework-managed inputs `fill_input()` is the helper for framework-managed inputs, but on X's bookmark search field it did not commit: the field stayed empty, then later appended instead of replacing, so a submit ran on the wrong query. Verify by reading the field's value back before pressing Enter — an appended value and a replaced one look identical in the DOM. Working fallback: native HTMLInputElement value setter plus an `input` InputEvent, then Enter.