koala73/worldmonitor · error · Error
Source card anchor collision: ${JSON.stringify(seen.get(anch
Error message
Source card anchor collision: ${JSON.stringify(seen.get(anchor))} and ${JSON.stringify(provider.provider)} both map to #${anchor} What it means
sourceCardAnchors builds a deterministic DOM anchor for each provider card as provider-<slug>-<sha1-prefix>. It throws when two distinct provider names hash/slug to the same anchor, because two cards sharing an id would break linking and duplicate-id validity. Note the guard: if the same provider name repeats, it is tolerated; only genuinely different providers colliding on one anchor throw.
Solutions
- Find the two colliding provider names in the error message and rename one so its slugged form is distinct.
- Review slugBase normalization; if it strips distinguishing characters, adjust the provider name or the slug function.
- Add a catalog lint/test that runs sourceCardAnchors over sourceCatalog to catch collisions before deploy.
Example fix
// before
{ provider: 'acme inc' }, { provider: 'Acme, Inc.' } // same anchor
// after
{ provider: 'acme-inc' }, { provider: 'acme-labs' } Defensive patterns
Strategy: validation
Validate before calling
const names = sourceCatalog.map((p) => String(p.provider ?? ''));
const anchors = new Set(names.map((n) => `provider-${slugBase(n)}-${createHash('sha1').update(n).digest('hex').slice(0, 16)}`));
if (anchors.size !== new Set(names).size) throw new Error('provider anchor collision in catalog'); Try / catch
try {
const anchors = sourceCardAnchors(sourceCatalog);
} catch (e) {
if (e.message.startsWith('Source card anchor collision')) {
console.error('Rename one of the colliding providers so slugs differ.');
process.exit(2);
}
throw e;
} Prevention
- Run sourceCardAnchors over the catalog in a unit test on every catalog change.
- Avoid provider names that differ only by case or punctuation.
- Keep slugBase normalization well documented and reviewed.
When it happens
Trigger: Adding a new provider to sourceCatalog whose name differs from an existing one only in characters that slugify away or whose sha1 first-16-hex collision maps to the same key string — e.g. names differing only by case/punctuation that slugBase normalizes identically.
Common situations: Renaming a provider in a way that slugBase makes identical to another (e.g. 'Acme, Inc.' vs 'acme inc'), or duplicating a catalog entry with a slightly edited label.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/10717ddb72ec0d58.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/crawlable-sources-page.mjs:776
* so the import would close a cycle. A local slug helper is also what the other
* generators in scripts/ do.
*/
export function sourceCardAnchors(sourceCatalog) {
const slugBase = (key) => String(key ?? '')
.normalize('NFKD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/&/g, ' and ')
.replace(/[^a-zA-Z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
.toLowerCase() || 'source';
const anchors = new Map();
const seen = new Map();
for (const provider of sourceCatalog) {
const key = String(provider.provider ?? '');
const anchor = `provider-${slugBase(key)}-${createHash('sha1').update(key).digest('hex').slice(0, 16)}`;
if (seen.has(anchor) && seen.get(anchor) !== provider.provider) {
throw new Error(
`Source card anchor collision: ${JSON.stringify(seen.get(anchor))} and ${JSON.stringify(provider.provider)} both map to #${anchor}`,
);
}
seen.set(anchor, provider.provider);
anchors.set(provider.provider, anchor);
}
return anchors;
}
export function buildSourcePages(sourceCatalog) {
return SOURCE_DOMAINS.flatMap((domain) => {
const providers = sourceCatalog.filter((provider) => provider.domainId === domain.id);
const pages = [];
for (let offset = 0; offset < providers.length; offset += 60) {
const number = offset / 60 + 1;
pages.push({
path: `/sources/${domain.id}/${number === 1 ? '' : `page/${number}/`}`,
name: `${domain.name}${number === 1 ? '' : ` — page ${number}`}`,View on GitHub (pinned to 7d06c8633d)