koala73/worldmonitor · error

is missing the switch-trigger section

Error message

 is missing the switch-trigger section

What it means

applyComparisonNarrative requires a switch-trigger section on every comparison page: a truthy switchHeading plus a non-empty switchProse array. This section explains when a reader should switch tools; it is mandatory and its absence fails the build.

Solutions

  1. Add switchHeading and a non-empty switchProse array to the slug's narrative entry.
  2. Author honest 'choose X when...' content for the section.
  3. Check field spelling against a passing narrative.
  4. Re-add prose if it was removed in a recent copy edit (git diff the narrative map).

Example fix

// before
'worldmonitor-vs-x': { evaluationHeading: 'How we evaluated', evaluationProse: [...] }
// after
'worldmonitor-vs-x': {
  evaluationHeading: 'How we evaluated',
  evaluationProse: [...],
  switchHeading: 'When to switch',
  switchProse: ['Switch to Flightradar24 only if you need ADS-B playback history beyond 30 days.'],
}
Defensive patterns

Strategy: validation

Validate before calling

if (!narrative.switchHeading || !narrative.switchProse?.length) {
  throw new Error(page.slug + ' missing switch-trigger section');
}

Type guard

const hasSwitchSection = (n) => typeof n.switchHeading === 'string' && n.switchHeading.trim() !== '' && Array.isArray(n.switchProse) && n.switchProse.length > 0;

Try / catch

try {
  page = applyComparisonNarrative(page);
} catch (e) {
  if (String(e.message).includes('missing the switch-trigger section')) {
    console.error('Add switchHeading + switchProse for:', e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Running the build when a slug's merged narrative lacks switchHeading or has an empty/missing switchProse array.

Common situations: Omitting the section when authoring a new narrative from scratch; a copy pass deleting the prose but leaving the heading; misspelled field names (switchTriggerProse instead of switchProse).

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/b444e17fbcd085c5. Report an issue: GitHub.

Appendix: source

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

    faqNames.add(key);
  }
  const merged = { ...page, ...narrative, faqs };
  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');

View on GitHub (pinned to 7d06c8633d)