mermaid-js/mermaid · error · Error

Both layout algorithms ${algorithm} and ${fallback} are not

Error message

Both layout algorithms ${algorithm} and ${fallback} are not registered.

What it means

Thrown by getRegisteredLayoutAlgorithm when neither the requested `algorithm` nor the `fallback` (default 'dagre') exists in layoutAlgorithms. Normally a missing algorithm silently falls back to dagre with a warning, so this throw means the fallback itself is unavailable — i.e. the default loaders were never registered or were cleared.

Source

Thrown at packages/mermaid/src/rendering-util/render.ts:149

  }

  return layoutRenderer.render(data4Layout, svg, internalHelpers, {
    algorithm: layoutDefinition.algorithm,
  });
};

/**
 * Get the registered layout algorithm. If the algorithm is not registered, use the fallback algorithm.
 */
export const getRegisteredLayoutAlgorithm = (algorithm = '', { fallback = 'dagre' } = {}) => {
  if (algorithm in layoutAlgorithms) {
    return algorithm;
  }
  if (fallback in layoutAlgorithms) {
    log.warn(`Layout algorithm ${algorithm} is not registered. Using ${fallback} as fallback.`);
    return fallback;
  }
  throw new Error(`Both layout algorithms ${algorithm} and ${fallback} are not registered.`);
};

View on GitHub (pinned to d93e9c88c0)

Solutions

  1. Ensure registerDefaultLayoutLoaders() (or registerLayoutLoaders with at least dagre) has run before calling getRegisteredLayoutAlgorithm.
  2. Don't override the fallback to an unregistered algorithm; rely on the default 'dagre' fallback.
  3. If using a custom build, explicitly register the loaders you need at app init.
  4. Check that the module side-effect import of render.ts isn't being tree-shaken away.

Example fix

// before — registry empty, custom unregistered fallback
getRegisteredLayoutAlgorithm('cose-bilkent', { fallback: 'myAlgo' });
// after
import { registerLayoutLoaders } from './render.js';
registerLayoutLoaders([{ name: 'dagre', loader: async () => await import('./dagre/index.js') }]);
getRegisteredLayoutAlgorithm('cose-bilkent'); // falls back to dagre
Defensive patterns

Strategy: fallback

Validate before calling

function pickLayout(algorithm: string, fallback = 'dagre'): string {
  // assume registry exposed; else hardcode known defaults
  const known = ['dagre', 'swimlane', 'cose-bilkent'];
  return known.includes(algorithm) ? algorithm : known.includes(fallback) ? fallback : 'dagre';
}

Type guard

function isRegistered(algo: string, registry: Record<string, unknown>): algo is string { return algo in registry; }

Try / catch

try { return getRegisteredLayoutAlgorithm(algo, { fallback }); } catch (e) { if (/not registered/.test(String(e))) { registerLayoutLoaders([dagreLoader]); return 'dagre'; } throw e; }

Prevention

When it happens

Trigger: Calling getRegisteredLayoutAlgorithm('cose-bilkent', { fallback: 'dagre' }) in an environment where registerDefaultLayoutLoaders hasn't run or layoutAlgorithms was emptied, or passing a custom fallback that also isn't registered. The render.ts module calls registerDefaultLayoutLoaders() at import (line 60), so this implies that didn't happen.

Common situations: Importing getRegisteredLayoutAlgorithm from a tree-shaken/minimal bundle that dropped the default-loader side effect, a test that mocks the registry empty, or a custom fallback name passed in config that was never registered. Rare in normal mermaid usage because dagre is always default-registered.

Related errors


AI-assisted analysis of mermaid-js/mermaid@d93e9c88c0 (2026-08-12). Data as JSON: /api/errors/a169a114a8b33329. Report an issue: GitHub.