{"record":{"id":"08cba864c042d489","repo":"koala73/worldmonitor","slug":"empty-sitemap-location","errorCode":null,"errorMessage":"empty sitemap: ${location}","messagePattern":"empty sitemap: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/seo-indexnow-submit.mjs","lineNumber":194,"sourceCode":"      method: 'GET',\n      redirect: 'manual',\n      signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n      headers: { Accept: 'application/xml', 'User-Agent': USER_AGENT },\n    });\n    if (response.status !== 200) throw new Error(`${location} returned ${response.status}, expected direct 200`);\n    const source = (await response.text()).trim();\n    const root = /^(?:<\\?xml[^?]*\\?>\\s*)?<(sitemapindex|urlset)\\b[^>]*>([\\s\\S]*)<\\/\\1>\\s*$/.exec(source);\n    if (!root) throw new Error(`invalid sitemap document: ${location}`);\n    const tag = root[1] === 'sitemapindex' ? 'sitemap' : 'url';\n    const entryPattern = new RegExp(`<!--[\\\\s\\\\S]*?-->|<${tag}>[\\\\s\\\\S]*?<\\\\/${tag}>`, 'g');\n    const entries = [...root[2].matchAll(entryPattern)].filter(([entry]) => !entry.startsWith('<!--'));\n    if (root[2].replace(entryPattern, '').trim()) throw new Error(`invalid sitemap entries: ${location}`);\n    const urls = entries.map(([entry]) => {\n      const locations = [...entry.matchAll(/<loc>\\s*([^<]+?)\\s*<\\/loc>/g)];\n      if (locations.length !== 1) throw new Error(`expected one location per sitemap entry: ${location}`);\n      return decodeXml(locations[0][1].trim());\n    });\n    if (urls.length === 0) throw new Error(`empty sitemap: ${location}`);\n    if (location === `${origin}/sitemap.xml`\n      && (root[1] !== 'sitemapindex' || urls.length !== SITEMAP_INDEX_MEMBERS.length\n        || new Set(urls).size !== urls.length || urls.some(url => !SITEMAP_INDEX_MEMBERS.includes(url)))) {\n      throw new Error('published root sitemap members do not match the declared inventory');\n    }\n    if (root[1] === 'sitemapindex') {\n      pending.push(...urls);\n    } else {\n      for (const url of urls) {\n        const page = new URL(url);\n        if (page.protocol !== 'https:' || !hosts.has(page.host) || page.username || page.password || page.hash || page.pathname.endsWith('.xml')) {\n          throw new Error(`invalid published page URL: ${url}`);\n        }\n        pages.add(url);\n      }\n    }\n  }\n  for (const family of ['docs', 'blog']) {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/seo-indexnow-submit.mjs#L176-L212","documentation":"After extracting <loc> values from every entry of a fetched sitemap, getPublishedBatches throws this when the resulting `urls` array is empty — the sitemap document exists and parses into entries but contains no locations (or no entries at all), so there is nothing to submit to IndexNow.","triggerScenarios":"Fetching `location` returns XML where the entry regex matches nothing (e.g. an empty `<urlset></urlset>` or `<sitemapindex></sitemapindex>`), or all matched candidates were HTML comments and were filtered out, leaving `urls.length === 0`.","commonSituations":"A fresh deploy publishes an empty sitemap before content is generated; the sitemap generator filtered out every URL (all pages excluded via robots/noindex); a cache or placeholder document is served instead of the real sitemap.","solutions":["Check why the sitemap generator produced no URLs — verify pages are eligible (not excluded by noindex/robots or build filters) and rerun the generator.","Fetch the sitemap manually to confirm whether the deployment serves the real file or an empty/placeholder document; redeploy if stale.","Purge the CDN/edge cache for the sitemap URL after regenerating.","For the root sitemap specifically, ensure SITEMAP_INDEX_MEMBERS are generated so the index is never empty."],"exampleFix":"// before (empty served sitemap)\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"></urlset>\n\n// after\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n  <url><loc>https://example.com/</loc></url>\n</urlset>","handlingStrategy":"validation","validationCode":"const xml = await res.text();\nif (!/<(url|sitemap)>[\\s\\S]*<\\/(url|sitemap)>/.test(xml)) {\n  throw new Error(`sitemap has no entries, skipping IndexNow submit: ${url}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const batches = await getPublishedBatches(origin);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('empty sitemap')) {\n    console.warn(`Sitemap is empty; nothing to submit: ${err.message}`);\n    return;\n  }\n  throw err;\n}","preventionTips":["Assert in CI that the generated sitemap contains at least one URL (and the root index lists all SITEMAP_INDEX_MEMBERS).","Verify the sitemap generator's exclusion filters (noindex, robots, build config) don't accidentally filter out every page.","Check the deployed sitemap after each deploy as a smoke test before running SEO scripts against it.","Purge CDN/edge cache so an empty placeholder never lingers after content exists."],"tags":["sitemap","seo","empty","validation"],"backgroundTag":"empty-result-set","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"}