# Troubleshooting

URL: /docs/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 `image` generator).
- **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". A `settings.defaults` key that matches no generator warns, too — it would
  never apply.

Run [`pro-visu doctor`](/docs/cli#pro-visu-doctor) to see every issue at once without generating.
For the field-by-field shapes, see [Configuration](/docs/configuration) and each
[generator](/docs/generators).

## "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 `URL` const in the scaffolded
  config — `init` guesses your dev port, but a custom setup may differ), or
- **Point at a deployed URL** instead, or
- **Configure a [managed server](/docs/configuration#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, `0`s, 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](/docs/recipes#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`](/docs/configuration#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_URL` to a reachable mirror of the
  [ffmpeg-static release assets](https://github.com/eugeneware/ffmpeg-static/releases), or
- **Bring your own:** set `FFMPEG_BIN` to any working local ffmpeg binary (it's honored as-is), or
- **Unsupported platform:** if there's no prebuilt binary for your OS/arch, `FFMPEG_BIN` is the
  way through.

## Captures fail on CI with a sandbox error

Most Linux CI runners need Chromium's sandbox disabled:

```ts
settings: {
  browser: { args: ["--no-sandbox"] },
}
```

Pair it with `--skip-server` when capturing an already-deployed URL. See the
[CI recipe](/docs/recipes#capture-a-deployed-url-in-ci).

## 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:

```ts
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.)
