Troubleshooting
The common first-run failures — unreachable URLs, blank or mid-animation captures, downloads behind proxies, CI sandboxing, memory — and their fixes.
Start with pro-visu doctor — it checks Node, the config (including every asset's options),
Chromium, ffmpeg, and whether your asset URLs respond, without generating anything.
The config is rejected or an option isn't recognized
generate (and doctor) validate the whole config before any heavy work, so mistakes fail in
seconds with a pointed path: message for each issue — e.g. options.motion.durationMs: Expected number. Two cases get a specific hint instead of a bare rejection:
- Unknown generator — misspelled or removed; the error lists the available ids, suggests the
closest for a typo, and explains a removal (e.g. the old
imagegenerator). - A moved or renamed option — pre-1.0 options that relocated (e.g. a scroll-reel's
hideSelectors→settings.capture.cleanup) report where they went rather than just "unrecognized key". Asettings.defaultskey that matches no generator warns, too — it would never apply.
Run pro-visu doctor to see every issue at once without generating.
For the field-by-field shapes, see Configuration and each
generator.
"Nothing is responding at http://localhost:…"
The capture URLs must point at something that's actually running. Either:
- Start your site on the port the config names (check the
URLconst in the scaffolded config —initguesses your dev port, but a custom setup may differ), or - Point at a deployed URL instead, or
- Configure a managed server so pro-visu builds, starts, captures, and stops the site itself — then you never have to pre-start anything.
Captures have blank gaps, zeros, or the wrong frame
Reveal-on-scroll sections, count-ups, scroll-snap, and other JS-driven animations capture
mid-flight — blank bands, 0s, or the wrong moment — because the frame is grabbed before they
settle. Disabling CSS transitions alone won't fix it: the visible state is gated in your JS, not
CSS. Tell the page it's being captured and render the settled state — see Capture mode: render a
settled page. For noise the site won't remove
itself (cookie banners, chat widgets), settings.capture.cleanup hides it tool-side; see
capture.
Chromium download fails (offline / corporate proxy)
The managed Chromium comes from Playwright's CDN on first run. Behind a proxy, set HTTPS_PROXY;
on an air-gapped network, point PLAYWRIGHT_DOWNLOAD_HOST at an internal mirror, or skip the
managed browser entirely with settings.browser.channel: "chrome" (uses your installed Chrome)
or settings.browser.executablePath.
ffmpeg download fails
ffmpeg (~80 MB) is fetched once into a shared cache on first generate. If the download fails:
- Proxy/offline: set
FFMPEG_BINARIES_URLto a reachable mirror of the ffmpeg-static release assets, or - Bring your own: set
FFMPEG_BINto any working local ffmpeg binary (it's honored as-is), or - Unsupported platform: if there's no prebuilt binary for your OS/arch,
FFMPEG_BINis the way through.
Captures fail on CI with a sandbox error
Most Linux CI runners need Chromium's sandbox disabled:
settings: {
browser: { args: ["--no-sandbox"] },
}Pair it with --skip-server when capturing an already-deployed URL. See the
CI recipe.
Run stops with a low-memory warning
Heavy plans manage memory automatically: a run with a real (non-test) wall re-execs with a
bigger Node heap sized from your machine's RAM, and every run watches its own memory and stops
gracefully before a crash — already-finished assets are kept, and are skipped on the next run
when --cache is on. If a run still stops, lower settings.concurrency or the asset's
workers.
Capturing pages behind a login
There's no dedicated auth option yet, but settings.capture.signals.cookies sets cookies on every
capture context before navigation — a session cookie carries auth exactly like a logged-in
browser would:
settings: {
capture: {
signals: {
cookies: [{ name: "session", value: process.env.CAPTURE_SESSION! }],
},
},
}Keep the value out of the config file (an env var, as above). For header-based schemes or SSO flows that can't be expressed as a cookie, capture a preview deployment with auth disabled instead.
The live dashboard misbehaves (or you want plain logs)
--verbose switches to plain log lines. PRO_VISU_LIVE=0 forces plain logs without the debug
noise; PRO_VISU_LIVE=1 forces the dashboard on a terminal that mis-reports as non-interactive.
A run was killed hard and left processes behind
Nothing to do — the next pro-visu generate detects the interrupted run's record, tears down
the orphaned server process tree and temp dirs, and then starts normally. (If the previous run
still looks active, it warns instead of killing it.)