vike
ReferenceBinaries

incident

Freezes the perishable evidence of a live run — journal segments, trace logs, the resolved run profile, the last engine snapshot and a redacted environment — into one timestamped bundle.

A live node's forensic trail is scattered across stores that overwrite themselves. The write-ahead command journal is mmap segments that prune. The JSON trace log rolls daily and can be size-capped. The resolved run profile is a file somebody can edit between runs. The process environment is gone the instant the process exits. When something goes wrong at 03:00 the operator needs a single artifact that pins all of it to the moment of the incident, before any of it rots.

incident is that artifact's collector. The binary is crates/vike-run/src/bin/incident.rs; the collection itself is crates/vike-run/src/incident.rs's run_incident. It is feature-free — no venue or native dependencies — so it builds in the default lane like any ordinary target.

incident --since 2h
incident --since 30m --out /var/vike/incidents
incident --since 1d --journal-dir data/journal --profile run.toml

--since is the one required flag and takes a Vike interval — 30s, 15m, 2h, 1d. A malformed value is an error, not a zero-length window: an empty bundle would read as "there was no evidence". vike-run incident … also works — one leading incident token is accepted and dropped, a second is not. The bundle's directory path is printed on stdout.

What it collects

Into incident-<UTC>/:

  • the journal segment files whose last write overlaps the window, gzipped;
  • the trace-log files from the resolved log directory whose last write overlaps the window, gzipped;
  • the resolved RunProfile TOML plus its FNV-1a64 hash, so a later edit to that file is detectable;
  • the latest EngineSnapshot and its state_hash, taken from the journal's last Snap;
  • git SHA and build info;
  • a redacted dump of the process environment.

Selection is select_overlapping: a file is in when its last write is at or after now - since, with the subtraction saturating so a huge window cannot overflow.

The archive is per-file gzip in a directory alongside a plain manifest.json rather than one .tar.gz. The module doc is explicit that this is a deliberate fallback — a single tarball needs a tar crate the crate cannot compile-check in its current build lane — and that bundling the directory afterwards is a trivial follow-up.

Safe to run against a live node

incident is a read-only collector. It opens the journal through vike_core::journal::CommandJournal's read_all — the lock-free entry point the journal module blesses for offline inspection tooling — never the writer. Nothing in the mount path calls it, the live core is untouched, and no existing struct gains a field for it.

Redaction

The environment dump is masked exactly the way the signers' manual Debug implementations mask their secrets (crates/vike-bridge-core/src/signer.rs): redact_secret_value returns *** followed by the last four characters, and nothing else. A value shorter than four characters gets the bare mask.

Which keys get masked is is_secret_key, and its doc states the bias: a generous, case-insensitive substring match, because over-redaction is safe — it costs an operator a non-secret flag — while a miss leaks a credential. It covers every credential shape the workspace uses (*_API_KEY, *_API_SECRET, *_API_PASSPHRASE, *_PRIVATE_KEY, the Polymarket PK family) plus tokens, mnemonics, seeds and signatures. Most VIKE_* runtime flags carry none of those needles and pass through verbatim. The ones whose names do are masked: the genuine secrets (VIKE_TRADEHUB_CONTROL_KEY, VIKE_TELEGRAM_BOT_TOKEN and their family) as intended, and VIKE_ALLOW_WITHDRAW_KEYS — an ordinary flag whose _KEYS suffix trips the _KEY needle — as over-redaction, which is the safe direction. build_manifest redacts internally, so the artifact is safe to share by construction.

Where the sources come from, and where the bundle lands

Every source is resolved the way a live node resolves it, never re-derived:

  • profile — --profile, else VIKE_RUN_PROFILE, through vike_core::run_profile's resolve_profile_path, so this bin cannot silently diverge from the resolver the node uses;
  • journal directory — --journal-dir, else VIKE_JOURNAL_DIR, else the loaded profile's journal sink;
  • log directory — the same four-layer precedence vike_log::resolve_log_dir gives a node (VIKE_LOG_DIR, then the flag, then the project's own settings/state/logs, then <exe_dir>). Before the project layer existed this resolved to <exe_dir>/logs and would now miss every log the collector was built to freeze;
  • output — --out, else the project's settings/state/incidents, else <exe_dir>.

The bundle is not scratch

The output default is deliberately not a temporary directory. A bundle is frozen post-mortem evidence — written precisely so it can be read after the thing that produced it is gone — so an owned scratch directory that deletes on drop, or a swept root that prunes to a bounded newest-N, would each destroy the only artifact this binary exists to make. It used to default to a fixed name under the system temp directory, which failed twice over: inside a container that directory is not the host's and does not survive a restart, and on a shared box whoever created it first owned it permanently.

File logging is switched off for this process, so the collector never writes into the very log directory it is about to freeze.

The parser rules worth knowing

A valued flag must be given a value, and a token beginning with -- is a flag, never a value. That rule closed a real defect: --out --profile used to parse cleanly and write the post-mortem bundle into a directory literally named --profile. A collector whose evidence lands somewhere nobody looks is the same as no collector. It is -- and not a bare -, so a negative number stays a legal value.

-h/--help exits 0 to stdout — it used to exit 1, which breaks set -e and any wrapper that checks a status. A --help in a value slot (--out --help) is still refused as a swallow, because succeeding there would silently discard the --out the operator typed. A repeated flag takes the last value, silently.

See the command journal for what the segments contain, and replay-journal for replaying them deterministically afterwards.

On this page