koala73/worldmonitor · error

${relativePath} is missing required live-pulse sections

Error message

${relativePath} is missing required live-pulse sections

What it means

resolveLatestLivePulseSnapshotPath validates the frozen live-pulse snapshot JSON. Besides matching the filename date to capturedAt, the snapshot must contain all required sections: countries, chokepoints, crises, and signalConvergence. If any is missing/falsy, it throws '<relativePath> is missing required live-pulse sections' so downstream pages can't render from a partial snapshot.

Solutions

  1. Run `npm run freeze:crawlable-live-pulse` to regenerate a complete snapshot with all four sections.
  2. If the snapshot was hand-edited, restore the missing section or regenerate rather than patching.
  3. Check the freeze script/template writes the exact key names: countries, chokepoints, crises, signalConvergence.
  4. Delete stale pre-schema snapshots and re-freeze so the latest file conforms.

Example fix

// before (snapshot JSON)
{ "capturedAt": "2026-09-15", "countries": [...], "crises": [...] }
// after
{ "capturedAt": "2026-09-15", "countries": [...], "chokepoints": [...], "crises": [...], "signalConvergence": [...] }
Defensive patterns

Strategy: validation

Validate before calling

const snap = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
for (const key of ['countries', 'chokepoints', 'crises', 'signalConvergence']) {
  if (!snap[key]) throw new Error(`${snapshotPath} missing ${key}`);
}

Type guard

const isCompleteSnapshot = (s) => Boolean(s?.countries && s?.chokepoints && s?.crises && s?.signalConvergence);

Prevention

When it happens

Trigger: Loading a snapshot file from the crawlable live-pulse directory whose parsed JSON lacks any of countries, chokepoints, crises, or signalConvergence keys (each must be truthy).

Common situations: A manually edited or truncated snapshot JSON; a new freeze script version writing a renamed section (e.g. chokepoint vs chokepoints); an old snapshot committed before signalConvergence existed; a failed freeze left a partial file.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/bad00dbd1f834a7c. Report an issue: GitHub.

Appendix: source

Thrown at scripts/build-crawlable-corpus.mjs:477

  const snapshotDir = repoPath(rootDir, RESILIENCE_SNAPSHOT_DIR);
  const candidates = readdirSync(snapshotDir)
    .map((filename) => ({ filename, match: filename.match(LIVE_PULSE_SNAPSHOT_RE) }))
    .filter(({ match }) => match)
    .sort((a, b) => b.match[1].localeCompare(a.match[1]));
  if (candidates.length === 0) {
    throw new Error(`No crawlable live-pulse snapshot found in ${RESILIENCE_SNAPSHOT_DIR}`);
  }

  const [{ filename, match }] = candidates;
  const relativePath = join(RESILIENCE_SNAPSHOT_DIR, filename);
  const snapshot = readJson(rootDir, relativePath);
  if (snapshot.capturedAt !== match[1]) {
    throw new Error(
      `${relativePath} filename date ${match[1]} does not match capturedAt ${snapshot.capturedAt}`,
    );
  }
  if (!snapshot.countries || !snapshot.chokepoints || !snapshot.crises || !snapshot.signalConvergence) {
    throw new Error(`${relativePath} is missing required live-pulse sections`);
  }
  const ageDays = livePulseSnapshotAgeDays(snapshot.capturedAt);
  if (ageDays > MAX_LIVE_PULSE_SNAPSHOT_AGE_DAYS) {
    throw new Error(
      `${relativePath} is ${Math.round(ageDays)} days old (max ${MAX_LIVE_PULSE_SNAPSHOT_AGE_DAYS}); `
      + 'run `npm run freeze:crawlable-live-pulse` to republish current values',
    );
  }
  return relativePath;
}

function formatStaticDateTime(iso) {
  const timestamp = Date.parse(iso);
  if (!Number.isFinite(timestamp)) return String(iso || '');
  return new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',

View on GitHub (pinned to 7d06c8633d)