koala73/worldmonitor · error · Error
invalid sitemap entries: ${location}
Error message
invalid sitemap entries: ${location} What it means
Within a recognized sitemap root the script strips comments and block-level <sitemap>/<url> tags via regex; if any non-whitespace content remains between/after those tags the document has unexpected inter-tag content and the script throws 'invalid sitemap entries: <location>', rejecting loosely-structured or injected markup.
Solutions
- Validate the sitemap against the sitemaps.org XSD and fix the generator to emit only standard <url>/<sitemap> children
- Remove stray text/unknown elements between the recognized tags
- Avoid hand-editing published sitemaps; regenerate them from the source of truth
- If the sitemap legitimately uses XML features the regex parser rejects, simplify the emitted markup to plain <loc> children
Example fix
// before <urlset> <url><loc>https://example.com/a</loc></url> generated by FooPlugin v2 <url><loc>https://example.com/b</loc></url> </urlset> // after <urlset> <url><loc>https://example.com/a</loc></url> <url><loc>https://example.com/b</loc></url> </urlset>
Defensive patterns
Strategy: validation
Validate before calling
const xml = (await (await fetch(url)).text()).trim();
const doc = new DOMParser().parseFromString(xml, 'application/xml');
if (doc.querySelector('parsererror')) console.warn(`${url}: malformed XML`); Try / catch
try {
await getPublishedBatches();
} catch (err) {
if (err.message.startsWith('invalid sitemap entries:')) {
const loc = err.message.split(': ').slice(1).join(': ');
logger.error({ loc }, 'unexpected content between sitemap tags');
} else throw err;
} Prevention
- Emit only standard <url>/<sitemap> children with <loc> inside
- Run sitemaps through XSD validation in CI
- Never hand-edit published sitemap files
When it happens
Trigger: The sitemap body contains stray text, unknown tags (e.g. custom elements between <url> blocks), unclosed or malformed <url> elements that the regex does not consume, CDATA or processing instructions outside the recognized pattern — anything left over after removing comments and tag blocks.
Common situations: Custom CMS injecting extra nodes into the sitemap; a template bug emitting text between <url> elements; sitemap edited by hand with invalid markup; an XML feature (CDATA sections, DOCTYPE entities) the simple regex parser does not model.
Related errors
- invalid sitemap document: ${location}
- expected one location per sitemap entry: ${location}
- invalid sitemap location: ${location}
- published sitemap tree exceeds 50 documents
- ${location} returned ${response.status}, expected direct 200
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/0f297990835ed473.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/seo-indexnow-submit.mjs:188
throw new Error(`invalid sitemap location: ${location}`);
}
if (seen.has(location)) continue;
seen.add(location);
if (seen.size > 50) throw new Error('published sitemap tree exceeds 50 documents');
const response = await fetchImpl(location, {
method: 'GET',
redirect: 'manual',
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
headers: { Accept: 'application/xml', 'User-Agent': USER_AGENT },
});
if (response.status !== 200) throw new Error(`${location} returned ${response.status}, expected direct 200`);
const source = (await response.text()).trim();
const root = /^(?:<\?xml[^?]*\?>\s*)?<(sitemapindex|urlset)\b[^>]*>([\s\S]*)<\/\1>\s*$/.exec(source);
if (!root) throw new Error(`invalid sitemap document: ${location}`);
const tag = root[1] === 'sitemapindex' ? 'sitemap' : 'url';
const entryPattern = new RegExp(`<!--[\\s\\S]*?-->|<${tag}>[\\s\\S]*?<\\/${tag}>`, 'g');
const entries = [...root[2].matchAll(entryPattern)].filter(([entry]) => !entry.startsWith('<!--'));
if (root[2].replace(entryPattern, '').trim()) throw new Error(`invalid sitemap entries: ${location}`);
const urls = entries.map(([entry]) => {
const locations = [...entry.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/g)];
if (locations.length !== 1) throw new Error(`expected one location per sitemap entry: ${location}`);
return decodeXml(locations[0][1].trim());
});
if (urls.length === 0) throw new Error(`empty sitemap: ${location}`);
if (location === `${origin}/sitemap.xml`
&& (root[1] !== 'sitemapindex' || urls.length !== SITEMAP_INDEX_MEMBERS.length
|| new Set(urls).size !== urls.length || urls.some(url => !SITEMAP_INDEX_MEMBERS.includes(url)))) {
throw new Error('published root sitemap members do not match the declared inventory');
}
if (root[1] === 'sitemapindex') {
pending.push(...urls);
} else {
for (const url of urls) {
const page = new URL(url);
if (page.protocol !== 'https:' || !hosts.has(page.host) || page.username || page.password || page.hash || page.pathname.endsWith('.xml')) {
throw new Error(`invalid published page URL: ${url}`);View on GitHub (pinned to 7d06c8633d)