koala73/worldmonitor · error · Error
formatCrawlableIntelBrief requires a country name
Error message
formatCrawlableIntelBrief requires a country name
What it means
formatCrawlableIntelBrief(text, countryName) converts a stored markdown-ish LLM intel brief into prerendered HTML for country pages. It requires a non-empty trimmed countryName because it rewrites the brief's 'means for' section title using the page's country name — stored briefs may still contain ISO codes from the TIER1-only prompt fallback (issue #7738). When countryName is missing, empty, or whitespace-only the function throws rather than emitting HTML with a blank or wrong title.
Solutions
- Pass the resolved country name as the second argument, e.g. formatCrawlableIntelBrief(brief.text, country.displayName).
- Guard before calling: if the country record has no non-blank name, skip and log instead of formatting.
- If upstream data can legitimately lack a name, decide on an explicit fallback (e.g. ISO code) upstream — never pass an empty string to satisfy the check.
- Grep all call sites of formatCrawlableIntelBrief after refactors to ensure none pass a renamed or missing field.
Example fix
// before
const html = formatCrawlableIntelBrief(brief.text, row.country_nm);
// after
const name = country?.displayName ?? row.name;
if (!name || !name.trim()) throw new Error(`no country name for ${row.code}`);
const html = formatCrawlableIntelBrief(brief.text, name); Defensive patterns
Strategy: type-guard
Validate before calling
if (!countryName || !String(countryName).trim()) {
throw new Error(`formatCrawlableIntelBrief: missing countryName for brief`);
} Type guard
const hasCountryName = (v) => typeof v === 'string' && v.trim().length > 0;
Try / catch
let html;
try {
html = formatCrawlableIntelBrief(brief.text, country.displayName);
} catch (err) {
if (err.message === 'formatCrawlableIntelBrief requires a country name') {
console.warn(`Skipping brief for ${country?.code}: missing display name`);
return null;
}
throw err;
} Prevention
- Pass the country record's canonical displayName field, not a loosely named column.
- Validate country records (non-blank name) before the page-generation loop.
- Grep all formatCrawlableIntelBrief call sites after renaming data fields.
- Treat an empty country name upstream as a data bug instead of defaulting to an empty string.
When it happens
Trigger: Calling formatCrawlableIntelBrief(briefText, countryName) with countryName undefined, null, '', or any value whose String() coercion trims to empty — typically during country-page generation when the country record failed to load or a refactored field name passes undefined.
Common situations: Generating crawlable country pages from cached/stored data where the display-name field is absent or empty for some records; a refactor renamed the data key so undefined is passed; iterating a partial country list; calling the formatter standalone (e.g. in a test) with only the text argument.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- /accuracy/ meta description must be 155–160 chars (got ${len
- writeAccuracySection requires the canonical DataCatalog iden
- Missing comparison narrative for ' + page.slug
- FAQ count must be 8-12, got ' + faqs.length
- duplicate FAQ question: ' + question
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/174004b82c9a446f.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/build-crawlable-corpus.mjs:3269
.trim();
if (next === current) break;
current = next;
}
return current;
}
function applyCrawlableBriefEmphasis(escaped) {
return escaped.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\*\*/g, '');
}
// Frozen intel briefs are markdown-ish LLM text. Country pages are prerendered
// HTML for crawlers, so convert emphasis and promote the five section titles
// rather than injecting the string into a <p>. Always rewrite the "means for"
// title from the page's country name: stored briefs still contain ISO codes
// from the TIER1-only prompt fallback (#7738).
export function formatCrawlableIntelBrief(text, countryName) {
const name = String(countryName || '').trim();
if (!name) throw new Error('formatCrawlableIntelBrief requires a country name');
const out = [];
let listOpen = false;
const closeList = () => {
if (listOpen) {
out.push(' </ul>');
listOpen = false;
}
};
const openList = () => {
if (!listOpen) {
out.push(' <ul>');
listOpen = true;
}
};
for (const rawLine of String(text || '').split('\n')) {
const trimmed = unwrapBriefEmphasisLine(rawLine.trim());
if (!trimmed) {View on GitHub (pinned to 7d06c8633d)