{"record":{"id":"b444e17fbcd085c5","repo":"koala73/worldmonitor","slug":"is-missing-the-switch-trigger-section","errorCode":null,"errorMessage":" is missing the switch-trigger section","messagePattern":" is missing the switch-trigger section","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/build-comparison-pages.mjs","lineNumber":477,"sourceCode":"    faqNames.add(key);\n  }\n  const merged = { ...page, ...narrative, faqs };\n  delete merged.extraFaqs;\n  const whyBody = (merged.whyWeWinBody ?? []).join(' ').replace(/\\s+/g, ' ').trim();\n  if (!whyBody) {\n    throw new Error(page.slug + ' is missing whyWeWinBody');\n  }\n  if (whyBody === merged.whyWeWin.replace(/\\s+/g, ' ').trim()) {\n    throw new Error(page.slug + ' whyWeWinBody must not repeat whyWeWin');\n  }\n  if (merged.heading && !(merged.headingProse?.length || merged.competitorProfiles?.length)) {\n    throw new Error(page.slug + ' H2 \"' + merged.heading + '\" has no following prose');\n  }\n  if (!merged.evaluationHeading || !merged.evaluationProse?.length) {\n    throw new Error(page.slug + ' is missing the evaluation section');\n  }\n  if (!merged.switchHeading || !merged.switchProse?.length) {\n    throw new Error(page.slug + ' is missing the switch-trigger section');\n  }\n  if (!merged.methodologyProse?.length) {\n    throw new Error(page.slug + ' is missing methodology prose');\n  }\n  return merged;\n}\n\nexport const COMPARISON_PAGES = COMPARISON_PAGE_SEEDS.map(applyComparisonNarrative);\n\nfunction renderParagraphs(paragraphs, escapeHtml) {\n  return (paragraphs ?? []).map((paragraph) => '      <p>' + escapeHtml(paragraph) + '</p>');\n}\n\nfunction renderHeadingSection(heading, paragraphs, escapeHtml, label) {\n  if (!heading) return [];\n  const body = renderParagraphs(paragraphs, escapeHtml);\n  if (body.length === 0) {\n    throw new Error((label || heading) + ' is missing following prose');","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/build-comparison-pages.mjs#L459-L495","documentation":"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.","triggerScenarios":"Running the build when a slug's merged narrative lacks switchHeading or has an empty/missing switchProse array.","commonSituations":"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).","solutions":["Add switchHeading and a non-empty switchProse array to the slug's narrative entry.","Author honest 'choose X when...' content for the section.","Check field spelling against a passing narrative.","Re-add prose if it was removed in a recent copy edit (git diff the narrative map)."],"exampleFix":"// before\n'worldmonitor-vs-x': { evaluationHeading: 'How we evaluated', evaluationProse: [...] }\n// after\n'worldmonitor-vs-x': {\n  evaluationHeading: 'How we evaluated',\n  evaluationProse: [...],\n  switchHeading: 'When to switch',\n  switchProse: ['Switch to Flightradar24 only if you need ADS-B playback history beyond 30 days.'],\n}","handlingStrategy":"validation","validationCode":"if (!narrative.switchHeading || !narrative.switchProse?.length) {\n  throw new Error(page.slug + ' missing switch-trigger section');\n}","typeGuard":"const hasSwitchSection = (n) => typeof n.switchHeading === 'string' && n.switchHeading.trim() !== '' && Array.isArray(n.switchProse) && n.switchProse.length > 0;","tryCatchPattern":"try {\n  page = applyComparisonNarrative(page);\n} catch (e) {\n  if (String(e.message).includes('missing the switch-trigger section')) {\n    console.error('Add switchHeading + switchProse for:', e.message);\n  } else throw e;\n}","preventionTips":["Include switchHeading/switchProse in the narrative starter template.","Validate all mandatory narrative fields in one pre-build audit instead of one throw at a time.","When removing prose in copy edits, check git diff for emptied required arrays."],"tags":["build-time","content-validation","missing-content"],"backgroundTag":"empty-required-field","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}