{"record":{"id":"bad00dbd1f834a7c","repo":"koala73/worldmonitor","slug":"relativepath-is-missing-required-live-pulse-sections","errorCode":null,"errorMessage":"${relativePath} is missing required live-pulse sections","messagePattern":"(.+?) is missing required live-pulse sections","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/build-crawlable-corpus.mjs","lineNumber":477,"sourceCode":"  const snapshotDir = repoPath(rootDir, RESILIENCE_SNAPSHOT_DIR);\n  const candidates = readdirSync(snapshotDir)\n    .map((filename) => ({ filename, match: filename.match(LIVE_PULSE_SNAPSHOT_RE) }))\n    .filter(({ match }) => match)\n    .sort((a, b) => b.match[1].localeCompare(a.match[1]));\n  if (candidates.length === 0) {\n    throw new Error(`No crawlable live-pulse snapshot found in ${RESILIENCE_SNAPSHOT_DIR}`);\n  }\n\n  const [{ filename, match }] = candidates;\n  const relativePath = join(RESILIENCE_SNAPSHOT_DIR, filename);\n  const snapshot = readJson(rootDir, relativePath);\n  if (snapshot.capturedAt !== match[1]) {\n    throw new Error(\n      `${relativePath} filename date ${match[1]} does not match capturedAt ${snapshot.capturedAt}`,\n    );\n  }\n  if (!snapshot.countries || !snapshot.chokepoints || !snapshot.crises || !snapshot.signalConvergence) {\n    throw new Error(`${relativePath} is missing required live-pulse sections`);\n  }\n  const ageDays = livePulseSnapshotAgeDays(snapshot.capturedAt);\n  if (ageDays > MAX_LIVE_PULSE_SNAPSHOT_AGE_DAYS) {\n    throw new Error(\n      `${relativePath} is ${Math.round(ageDays)} days old (max ${MAX_LIVE_PULSE_SNAPSHOT_AGE_DAYS}); `\n      + 'run `npm run freeze:crawlable-live-pulse` to republish current values',\n    );\n  }\n  return relativePath;\n}\n\nfunction formatStaticDateTime(iso) {\n  const timestamp = Date.parse(iso);\n  if (!Number.isFinite(timestamp)) return String(iso || '');\n  return new Intl.DateTimeFormat('en-US', {\n    year: 'numeric',\n    month: 'short',\n    day: 'numeric',","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/build-crawlable-corpus.mjs#L459-L495","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Run `npm run freeze:crawlable-live-pulse` to regenerate a complete snapshot with all four sections.","If the snapshot was hand-edited, restore the missing section or regenerate rather than patching.","Check the freeze script/template writes the exact key names: countries, chokepoints, crises, signalConvergence.","Delete stale pre-schema snapshots and re-freeze so the latest file conforms."],"exampleFix":"// before (snapshot JSON)\n{ \"capturedAt\": \"2026-09-15\", \"countries\": [...], \"crises\": [...] }\n// after\n{ \"capturedAt\": \"2026-09-15\", \"countries\": [...], \"chokepoints\": [...], \"crises\": [...], \"signalConvergence\": [...] }","handlingStrategy":"validation","validationCode":"const snap = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));\nfor (const key of ['countries', 'chokepoints', 'crises', 'signalConvergence']) {\n  if (!snap[key]) throw new Error(`${snapshotPath} missing ${key}`);\n}","typeGuard":"const isCompleteSnapshot = (s) => Boolean(s?.countries && s?.chokepoints && s?.crises && s?.signalConvergence);","tryCatchPattern":null,"preventionTips":["Never hand-edit frozen snapshot JSON; always regenerate via the freeze script.","Version the snapshot schema and migrate old files instead of leaving partial ones."],"tags":["build","schema-validation","snapshot","live-pulse"],"backgroundTag":"schema-validation-failed","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}