koala73/worldmonitor · error · Error
Report ${report.id}: ${role} ${id} has no valid route in the
Error message
Report ${report.id}: ${role} ${id} has no valid route in the chokepoint registry What it means
After slug validation, the research-reports builder resolves each referenced chokepoint (focus and context) through the chokepoint registry to build its route. If a referenced chokepoint id has no entry whose slug passes SLUG_PATTERN, the link would be dead, so the build throws identifying the report, role, and id.
Solutions
- Fix the report's focusChokepointId / contextChokepointIds to reference an id that exists in the chokepoint registry.
- If the chokepoint was intentionally removed, remove or replace the reference in the report data.
- Regenerate/rebuild the chokepoint registry so chokepointSlugById is current before the reports build.
- Consider a data-level referential-integrity check so bad ids fail at authoring time.
Example fix
// before
{ id: 'hormuz-strait', contextChokepointIds: ['suez-canal-old'] }
// after
{ id: 'hormuz-strait', contextChokepointIds: ['suez-canal'] } Defensive patterns
Strategy: validation
Validate before calling
const missing = [report.focusChokepointId, ...report.contextChokepointIds]
.filter((id) => !chokepointSlugById.has(id));
if (missing.length) throw new Error(`unknown chokepoint ids: ${missing.join(', ')}`); Try / catch
try { renderReport(report); } catch (e) { console.error(e.message); /* fix registry or report refs */ } Prevention
- Reference chokepoints only via ids generated from the registry.
- Run a referential-integrity lint over report data before builds.
- When removing a chokepoint, grep reports for its id first.
When it happens
Trigger: A report's focusChokepointId or an entry in contextChokepointIds references an id absent from chokepointSlugById (typo, deleted chokepoint, registry not yet regenerated) when the reports build runs.
Common situations: Renaming/removing a chokepoint in the registry without updating reports that reference it; typos in report front-matter ids; registry built from a different data revision than the reports.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Comparison measurement requires the captured snapshot date
- renderCountryDevelopments requires a country name
- Report slug/id must match ${SLUG_PATTERN}: ${report.slug} /
- ${label} HTTP 400
- Could not resolve ${JSON.stringify(echoCountryInput(raw))} t
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/e86b7d8b12fe4e6c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/build-research-reports.mjs:718
tpl,
baseUrl,
lastmod,
chokepointSlugById,
dataCatalog,
includedInDataCatalog,
}) {
const { escapeHtml, absoluteUrl, breadcrumbLd, withUtmSource, pageDocument } = tpl;
const SLUG_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
if (!SLUG_PATTERN.test(report.slug) || !SLUG_PATTERN.test(report.id)) {
throw new Error(`Report slug/id must match ${SLUG_PATTERN}: ${report.slug} / ${report.id}`);
}
for (const [role, ids] of [
['focusChokepointId', [report.focusChokepointId]],
['contextChokepointId', report.contextChokepointIds],
]) {
for (const id of ids) {
if (!SLUG_PATTERN.test(chokepointSlugById.get(id) ?? '')) {
throw new Error(`Report ${report.id}: ${role} ${id} has no valid route in the chokepoint registry`);
}
}
}
const chokepointSlug = chokepointSlugById.get(report.focusChokepointId);
const path = `/research/${report.slug}/`;
const canonical = absoluteUrl(baseUrl, path);
const focus = snapshot.chokepoints[report.focusChokepointId];
const resolve = (text) => resolveMetricTokens(escapeHtml(text), metrics, escapeHtml);
const m = (id) => {
const metric = metrics.get(id);
if (!metric) throw new Error(`Unknown metric: ${id}`);
return metric;
};
// Plain-text description for surfaces that cannot carry <data> markup; the
// definition writes it with {{m:...}} tokens so its numbers cannot drift
// from the computed metrics.
const description = resolvePlainMetricTokens(report.description, metrics);
const partialMonth = focus.observationEnd.slice(0, 7);View on GitHub (pinned to 7d06c8633d)