koala73/worldmonitor · error
needs a World Monitor measurement explanation
Error message
needs a World Monitor measurement explanation
What it means
After validating the snapshot date, renderMeasurement looks up COMPARISON_MEASUREMENTS[slug] for the page's 'How World Monitor measures this' paragraphs. Every comparison slug must have a measurement explanation; if the map has no entry (or an empty array), the build throws '<slug> needs a World Monitor measurement explanation'.
Solutions
- Add a COMPARISON_MEASUREMENTS entry keyed by the exact slug with at least one paragraph string.
- If the slug was renamed, rename the COMPARISON_MEASUREMENTS key to match the seed slug.
- Restore the deleted/emptied measurement paragraphs for that slug.
Example fix
// before
const COMPARISON_MEASUREMENTS = {
'chokepoint-monitoring-tools': [...],
};
// after
const COMPARISON_MEASUREMENTS = {
'chokepoint-monitoring-tools': [...],
'country-instability-index-alternatives': [
'World Monitor computes the Country Instability Index from ...',
],
}; Defensive patterns
Strategy: validation
Validate before calling
const missing = COMPARISON_PAGE_SEEDS.filter((s) => !(COMPARISON_MEASUREMENTS[s.slug]?.length));
if (missing.length) throw new Error(`slugs missing measurement prose: ${missing.map((s) => s.slug).join(', ')}`);
Prevention
- Treat COMPARISON_PAGE_SEEDS and COMPARISON_MEASUREMENTS as one unit: update both in the same commit.
- Add a build-time test asserting seed slugs and measurement keys match exactly.
When it happens
Trigger: Adding a new slug to COMPARISON_PAGE_SEEDS without adding a matching key in COMPARISON_MEASUREMENTS, or an entry whose value is [] — renderMeasurement then finds paragraphs?.length falsy.
Common situations: New comparison page added; slug renamed in the seeds but not in COMPARISON_MEASUREMENTS (typo or rebrand); measurement content removed pending rewrite, leaving an empty array.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- is missing methodology prose
- profile "' + profile.name + '" has no prose
- Missing comparison narrative for ' + page.slug
- is missing whyWeWinBody
- is missing the evaluation section
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/8cde76ec1542f1a1.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/build-comparison-pages.mjs:583
'@type': 'WebPage',
'@id': url + '#webpage',
name,
description,
url,
inLanguage: 'en-US',
dateModified: lastmod,
isPartOf: { '@id': new URL('/#website', baseUrl).href },
breadcrumb: { '@id': url + '#breadcrumb' },
mainEntity: { '@id': faqId },
};
}
function renderMeasurement(slug, snapshotDate, escapeHtml) {
if (!/^\d{4}-\d{2}-\d{2}$/.test(snapshotDate ?? '')) {
throw new Error('Comparison measurement requires the captured snapshot date');
}
const paragraphs = COMPARISON_MEASUREMENTS[slug];
if (!paragraphs?.length) throw new Error(slug + ' needs a World Monitor measurement explanation');
const maritime = slug === 'chokepoint-monitoring-tools';
const snapshotPath = maritime ? '/chokepoints/status.json' : '/country-instability-index/cii-ranking.json';
return [
' <h2>How World Monitor measures this</h2>',
...renderParagraphs(paragraphs, escapeHtml),
' <p>Coverage: the <a href="/sources/">source catalog</a> lists ' + escapeHtml(formatCount(WORLD_MONITOR_PROVIDER_COUNT)) + ' active providers across the product, not per metric. Availability varies by source and location.</p>',
' <p data-measurement-snapshot><a href="' + snapshotPath + '">Published ' + (maritime ? 'chokepoint status' : 'country instability') + ' snapshot</a>, captured <time datetime="' + escapeHtml(snapshotDate) + '">' + escapeHtml(snapshotDate) + '</time>. This reference remains dated when live values change.</p>',
];
}
function renderComparePage(page, { tpl, baseUrl, lastmod, snapshotDate }) {
const { escapeHtml, breadcrumbLd, pageDocument } = tpl;
const pageUrl = new URL(page.path, baseUrl).href;
const description = page.metaDescription ?? (page.h1
+ ' - ' + page.claim
+ '. Full comparison matrix, honest concessions, and FAQs.');
assertMetaDescription(description, page.slug);
View on GitHub (pinned to 7d06c8633d)