my_backup Dynalist Capture Timeout Fix
Section titled “my_backup Dynalist Capture Timeout Fix”What was fixed
Section titled “What was fixed”hooks/BackupDynalist.py (Selenium script that logs into Dynalist and downloads a backup zip during the daily my_backup pre-backup hooks) started failing 2026-07-07 and 2026-07-08, both times at the same point: a WebDriverWait(driver, 10) timeout waiting for the post-login hamburger menu (AppHeader-mainMenu class) to become clickable, after email/password entry and sign-in click succeeded.
Confirmed via a live fetch of https://dynalist.io/login that the login-page selectors (EmailField, input[type=password], js-login button) were still valid — the break was specifically post-login, not the login form itself. Could not determine the exact cause (Dynalist DOM change vs. bot-detection block vs. silent login failure) from the WSL session that diagnosed this, since that page requires a live authenticated browser and WSL→Windows interop was down at the time (see 2026-07-08_web-deploy-focus-crash-and-wsl-interop.md — fixed later the same day, but not yet applied when this task started).
Rather than guess at a DOM/selector fix, the script was hardened so the next failure (if any) produces enough evidence to diagnose without re-running blind:
- Real bug fixed:
except ValueErrornever caught Selenium’sTimeoutException/WebDriverException, so the script crashed with an unhandled traceback instead of failing cleanly. Broadened toexcept (ValueError, WebDriverException). - Added failure diagnostics: on any caught
WebDriverException, the script now saves a screenshot, full page source, and current URL/title tologs/dynalist_debug/failure_<timestamp>.*. - Security hygiene: moved the hardcoded plaintext
EMAIL/PASSWORDout of source into.env(DYNALIST_EMAIL,DYNALIST_PASSWORD), matching thePROJECT_ROOT+load_dotenv()pattern already used by every script insrc/my_backup/.
The 2026-07-09 08:00 scheduled run succeeded ([OK] Dynalist Capture in backup.log; fresh dynalist-backup.zip written; no dynalist_debug/ artifacts) — Talbot confirmed “working again.” Whatever caused the two-day outage was transient (or WSL interop being down was somehow a factor in how it was first investigated, not in the actual failure) — it did not recur once the exception-handling bug was fixed, so no DOM/selector change was ultimately needed.
Files changed
Section titled “Files changed”hooks/BackupDynalist.py— broadened exception handling, added failure-diagnostic capture, moved credentials to.env.env— addedDYNALIST_EMAIL/DYNALIST_PASSWORD(gitignored, not committed)
Key gotchas
Section titled “Key gotchas”- A narrow
except ValueErroraround Selenium code silently swallows nothing and catches nothing useful — Selenium raisesWebDriverExceptionsubclasses (TimeoutException, etc.), neverValueError. Any Selenium hook script needsexcept (ValueError, WebDriverException)or broader, or failures crash unhandled with no clean error path. - When a Selenium-based scraper against a third-party site fails, don’t guess at a new selector — capture forensic evidence on failure instead (screenshot + page source + URL to a debug folder). Third-party UI changes, anti-bot blocks, and silent auth failures all look identical from a log line alone; only the captured page state tells them apart.
- A WSL Claude session cannot verify Windows-native Selenium/browser scripts live — no local Chrome, and WSL→Windows interop may be unavailable (as it was here, until fixed by an unrelated task the same day). Diagnose from logs, make closely-scoped code fixes, and ask the user to trigger one real run rather than guessing.