paperclipai/paperclip · error · Error

: ambiguous brand alias

Error message

${row.slug}: ambiguous brand alias ${name}

What it means

The app brand validation script throws this when two different provider rows normalize to the same brand key via normalizeBrandKey (slug, provider name, or any alias colliding across rows). Ambiguous aliases would make brand lookups non-deterministic, so the manifest is rejected.

Solutions

  1. Find the colliding name from the message and change the alias on the newer row to something unambiguous.
  2. If both rows genuinely refer to the same provider, merge the rows instead of duplicating.
  3. Check normalization rules (case/punctuation folding) and pick a name that stays distinct after normalization.
  4. Re-run the validation script to confirm no further collisions.

Example fix

// before (collides with provider "acme")
{ "slug": "acme-cloud", "provider": "Acme Cloud", "aliases": ["Acme"] }
// after
{ "slug": "acme-cloud", "provider": "Acme Cloud", "aliases": ["Acme Cloud Platform"] }
Defensive patterns

Strategy: validation

Validate before calling

function norm(s){return s.toLowerCase().replace(/[^a-z0-9]/g,'');}
const seen = new Map();
for (const r of manifest.providers)
  for (const n of [r.slug, r.provider, ...(r.aliases ?? [])]) {
    const k = norm(n);
    if (seen.has(k) && seen.get(k) !== r.slug) throw new Error(`Ambiguous alias ${n}`);
    seen.set(k, r.slug);
  }

Try / catch

try { validateManifest(manifest); } catch (e) {
  if (e.message.includes('ambiguous brand alias')) {
    console.error('Rename or merge the colliding provider/alias before retrying');
  } else throw e;
}

Prevention

When it happens

Trigger: Running validateManifest where row A's slug/provider/alias normalizes to the same key as row B's (keys.has(key) && keys.get(key) !== row.slug), e.g. two providers aliasing "GitHub" or a provider name equal to another row's slug.

Common situations: Adding a new provider whose alias duplicates an existing brand; case/spacing variants like "acme" vs "Acme" normalizing to the same key; renaming a provider so it now collides with another slug.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/01f918f49eeeca12. Report an issue: GitHub.

Appendix: source

Thrown at scripts/app-brand-validation.mjs:38

    || /\b(?:[\w-]+:)?href\s*=\s*["'](?!#)/i.test(svg)
    || /@import|@media|url\(\s*["']?(?!#)[^)]*\)|(?:javascript|data|https?):|\\/i.test(svg.replace(/xmlns(?::[\w-]+)?\s*=\s*["'][^"']*["']/gi, ""))) {
    throw new Error(`${filename}: unsafe SVG feature, external resource, theme media query, or embedded raster wrapper`);
  }
}

export function validateManifest(manifest, readAsset) {
  if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.providers)) throw new Error("Invalid brand manifest");
  const keys = new Map();
  const slugs = new Set();
  for (const row of manifest.providers) {
    if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(row.slug) || slugs.has(row.slug)) throw new Error(`Duplicate or invalid slug: ${row.slug}`);
    slugs.add(row.slug);
    if (typeof row.provider !== "string" || !row.provider.trim()) throw new Error(`${row.slug}: missing provider name`);
    const aliases = row.aliases ?? [];
    if (!Array.isArray(aliases) || aliases.some((alias) => typeof alias !== "string" || !alias.trim())) throw new Error(`${row.slug}: invalid aliases`);
    for (const name of [row.slug, row.provider, ...aliases]) {
      const key = normalizeBrandKey(name);
      if (keys.has(key) && keys.get(key) !== row.slug) throw new Error(`${row.slug}: ambiguous brand alias ${name}`);
      keys.set(key, row.slug);
    }
    for (const asset of new Set([row.localAsset, ...(row.darkAsset === undefined ? [] : [row.darkAsset])])) {
      if (typeof asset !== "string" || !assetPathPattern.test(asset)) throw new Error(`${row.slug}: invalid asset path`);
      validateArtwork(readAsset(asset), asset);
    }
  }
  return manifest.providers.length;
}

View on GitHub (pinned to 3f1d897a7c)