{"record":{"id":"a67927b351ac72fb","repo":"mermaid-js/mermaid","slug":"invalid-icon-loader-must-have-a-name-property-w","errorCode":null,"errorMessage":"Invalid icon loader. Must have a \"name\" property with non-empty string value.","messagePattern":"Invalid icon loader\\. Must have a \"name\" property with non-empty string value\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mermaid/src/rendering-util/icons.ts","lineNumber":32,"sourceCode":"  name: string;\n  icons: IconifyJSON;\n}\n\nexport type IconLoader = AsyncIconLoader | SyncIconLoader;\n\nexport const unknownIcon: IconifyIcon = {\n  body: '<g><rect width=\"80\" height=\"80\" style=\"fill: #087ebf; stroke-width: 0px;\"/><text transform=\"translate(21.16 64.67)\" style=\"fill: #fff; font-family: ArialMT, Arial; font-size: 67.75px;\"><tspan x=\"0\" y=\"0\">?</tspan></text></g>',\n  height: 80,\n  width: 80,\n};\n\nconst iconsStore = new Map<string, IconifyJSON>();\nconst loaderStore = new Map<string, AsyncIconLoader['loader']>();\n\nexport const registerIconPacks = (iconLoaders: IconLoader[]) => {\n  for (const iconLoader of iconLoaders) {\n    if (!iconLoader.name) {\n      throw new Error(\n        'Invalid icon loader. Must have a \"name\" property with non-empty string value.'\n      );\n    }\n    log.debug('Registering icon pack:', iconLoader.name);\n    if ('loader' in iconLoader) {\n      loaderStore.set(iconLoader.name, iconLoader.loader);\n    } else if ('icons' in iconLoader) {\n      iconsStore.set(iconLoader.name, iconLoader.icons);\n    } else {\n      log.error('Invalid icon loader:', iconLoader);\n      throw new Error('Invalid icon loader. Must have either \"icons\" or \"loader\" property.');\n    }\n  }\n};\n\nconst getRegisteredIconData = async (iconName: string, fallbackPrefix?: string) => {\n  const data = stringToIcon(iconName, true, fallbackPrefix !== undefined);\n  if (!data) {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/mermaid-js/mermaid/blob/d93e9c88c01a599c062ee6a3f1462e3558ac6b90/packages/mermaid/src/rendering-util/icons.ts#L14-L50","documentation":"Thrown by registerIconPacks when an icon loader object in the passed array has no `name` property or an empty-string name. The name is used as the registry key (it overrides the iconify pack prefix), so every loader must declare one. This is a fail-fast guard before the loader/icons branches are even considered.","triggerScenarios":"Calling mermaid.registerIconPacks([{ loader: () => import('@iconify-json/logos') }]) (object with only a `loader` key), or registerIconPacks([{ name: '', icons }]) (empty-string name), or registerIconPacks([{}]) (empty object). Any element where `!iconLoader.name` is truthy triggers it.","commonSituations":"Typo on the `name` field (e.g. `Name` or `packName`), destructuring a pack and forgetting to spread `name`, or building loader objects dynamically and skipping the name when a fetch/import succeeds. Also when copying docs examples and accidentally dropping the `name` line.","solutions":["Add a non-empty `name` string to every loader object passed to registerIconPacks; it becomes the prefix users reference in diagrams (e.g. name: 'logos').","If using a static iconify JSON pack, set name to the pack's own prefix: name: icons.prefix.","Type-check your array against the exported IconLoader (AsyncIconLoader | SyncIconLoader) union so the TS compiler rejects nameless objects before runtime.","Log the offending element: the log.error call only fires for the icons/loader branch, so for the name guard inspect each entry manually before calling."],"exampleFix":"// before\nmermaid.registerIconPacks([\n  { loader: () => import('@iconify-json/logos').then((m) => m.icons) },\n]);\n// after\nmermaid.registerIconPacks([\n  {\n    name: 'logos',\n    loader: () => import('@iconify-json/logos').then((m) => m.icons),\n  },\n]);","handlingStrategy":"validation","validationCode":"function isValidIconLoader(x: unknown): x is { name: string } & Record<string, unknown> {\n  return typeof x === 'object' && x !== null && typeof (x as any).name === 'string' && (x as any).name.length > 0;\n}\nconst safe = iconLoaders.filter(isValidIconLoader);\nif (safe.length !== iconLoaders.length) throw new Error('one or more icon loaders lack a non-empty name');\nmermaid.registerIconPacks(safe);","typeGuard":"function isNamedIconLoader(x: unknown): x is { name: string } {\n  return typeof x === 'object' && x !== null && typeof (x as any).name === 'string' && (x as any).name.trim() !== '';\n}","tryCatchPattern":"try { mermaid.registerIconPacks(loaders); } catch (e) { console.error('icon pack registration failed:', e); throw e; }","preventionTips":["Type your loader array as IconLoader[] so the compiler rejects nameless objects.","Build loader objects from a single factory that always sets name.","Run registerIconPacks at app boot, not lazily, so failures surface early."],"tags":["icons","configuration","registericonpacks","validation"],"backgroundTag":null,"analyzedSha":"d93e9c88c01a599c062ee6a3f1462e3558ac6b90","analyzedAt":"2026-08-12T06:23:11.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}