koala73/worldmonitor · error

is missing methodology prose

Error message

 is missing methodology prose

What it means

build-comparison-pages.mjs applies narrative content to comparison page seeds via applyComparisonNarrative. It validates that each merged page has an evaluation section, a switch-trigger section, and methodology prose. If a page's methodologyProse array is empty or undefined, the build fails with '<slug> is missing methodology prose' so no comparison page ships without required methodology content.

Solutions

  1. Add a non-empty methodologyProse array (strings of paragraph text) to the affected page's seed in COMPARISON_PAGE_SEEDS.
  2. If the page uses a narrative override/merge source, ensure the merge output includes methodologyProse rather than replacing it with undefined.
  3. Run the build script to confirm the slug named in the message now passes applyComparisonNarrative.

Example fix

// before
{
  slug: 'country-instability-index-alternatives',
  methodologyProse: [],
}
// after
{
  slug: 'country-instability-index-alternatives',
  methodologyProse: [
    'World Monitor derives its index from N providers, weighted by ...',
  ],
}
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(page.methodologyProse) || page.methodologyProse.length === 0) {
  throw new Error(`${page.slug}: methodologyProse must be a non-empty array before building`);
}

Type guard

const hasProse = (v) => Array.isArray(v) && v.length > 0 && v.every((p) => typeof p === 'string' && p.trim() !== '');

Prevention

When it happens

Trigger: Calling applyComparisonNarrative (directly or via COMPARISON_PAGES construction at module load) with a seed whose merged narrative has no methodologyProse array, or methodologyProse set to [] / null.

Common situations: Adding a new COMPARISON_PAGE_SEEDS entry without copying the full narrative block from an existing seed; a content edit accidentally deleting the methodologyProse key; a merge/override object that replaces narrative fields and drops methodologyProse.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at scripts/build-comparison-pages.mjs:480

  delete merged.extraFaqs;
  const whyBody = (merged.whyWeWinBody ?? []).join(' ').replace(/\s+/g, ' ').trim();
  if (!whyBody) {
    throw new Error(page.slug + ' is missing whyWeWinBody');
  }
  if (whyBody === merged.whyWeWin.replace(/\s+/g, ' ').trim()) {
    throw new Error(page.slug + ' whyWeWinBody must not repeat whyWeWin');
  }
  if (merged.heading && !(merged.headingProse?.length || merged.competitorProfiles?.length)) {
    throw new Error(page.slug + ' H2 "' + merged.heading + '" has no following prose');
  }
  if (!merged.evaluationHeading || !merged.evaluationProse?.length) {
    throw new Error(page.slug + ' is missing the evaluation section');
  }
  if (!merged.switchHeading || !merged.switchProse?.length) {
    throw new Error(page.slug + ' is missing the switch-trigger section');
  }
  if (!merged.methodologyProse?.length) {
    throw new Error(page.slug + ' is missing methodology prose');
  }
  return merged;
}

export const COMPARISON_PAGES = COMPARISON_PAGE_SEEDS.map(applyComparisonNarrative);

function renderParagraphs(paragraphs, escapeHtml) {
  return (paragraphs ?? []).map((paragraph) => '      <p>' + escapeHtml(paragraph) + '</p>');
}

function renderHeadingSection(heading, paragraphs, escapeHtml, label) {
  if (!heading) return [];
  const body = renderParagraphs(paragraphs, escapeHtml);
  if (body.length === 0) {
    throw new Error((label || heading) + ' is missing following prose');
  }
  return ['      <h2>' + escapeHtml(heading) + '</h2>', ...body];
}

View on GitHub (pinned to 7d06c8633d)