paperclipai/paperclip · error · Error
: missing provider name
Error message
${row.slug}: missing provider name What it means
The app brand validation script throws this when a provider row in the brand manifest has a provider field that is not a non-empty string (missing, non-string, or whitespace-only). Every provider entry must carry a human-readable provider name.
Solutions
- Add a non-empty provider string to the offending row identified by the slug in the message.
- Fix typos where provider was written under a different key name (e.g. `name` instead of `provider`).
- Re-run scripts/app-brand-validation.mjs to confirm the manifest validates.
Example fix
// before
{ "slug": "acme", "aliases": ["Acme Corp"] }
// after
{ "slug": "acme", "provider": "Acme Corporation", "aliases": ["Acme Corp"] } Defensive patterns
Strategy: validation
Validate before calling
const bad = manifest.providers.filter(r => typeof r.provider !== 'string' || !r.provider.trim());
if (bad.length) throw new Error(`Missing provider name for: ${bad.map(r => r.slug)}`); Type guard
const hasProviderName = (row) => typeof row?.provider === 'string' && row.provider.trim().length > 0;
Try / catch
try { validateManifest(manifest); } catch (e) {
if (e.message.includes('missing provider name')) {
const slug = e.message.split(':')[0];
console.error(`Fill in provider name for ${slug} in the brand manifest`);
} else throw e;
} Prevention
- Use a JSON schema or typed interface for brand manifest rows so missing provider fails typecheck.
- Run the brand validation script in CI before merging manifest changes.
- Scaffold new provider rows from a template that includes provider.
When it happens
Trigger: Running validateManifest on a manifest whose providers[] entry omits the `provider` key, sets it to a non-string value, or sets it to "" or whitespace.
Common situations: Hand-editing the brand manifest and forgetting the provider field; a code generation step that writes an empty provider; a new catalog entry scaffolded without a provider name.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Worktree seed manifest is missing source path diagnostics.
- does not carry submitted form data
- : invalid AppDefinition
- Durable PRP run attachment template is invalid.
- Invalid or oversized current.json
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/6f188cf384b30453.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/app-brand-validation.mjs:33
const svg = bytes.toString("utf8");
if (!filename.endsWith(".svg") || (!/<svg\b[^>]*\bviewBox\s*=\s*["'][^"']+["']/i.test(svg) && !(/<svg\b[^>]*\bwidth\s*=\s*["'][0-9.]+(?:px)?["']/i.test(svg) && /<svg\b[^>]*\bheight\s*=\s*["'][0-9.]+(?:px)?["']/i.test(svg)))) {
throw new Error(`${filename}: SVG requires a viewBox or intrinsic width and height`);
}
if (/<!DOCTYPE|<!ENTITY|<\?xml-stylesheet|&#|<\s*(?:[\w-]+:)?(?:script|foreignObject|image|feImage|iframe|object|embed|animate\w*|set|a)\b|\bon[\w-]+\s*=/i.test(svg)
|| /\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)