mermaid-js/mermaid · error

Axes must be populated before curves for reference entries

Error message

Axes must be populated before curves for reference entries

What it means

Thrown by the radar diagram's computeCurveEntries() when a curve's entries reference axes by name (entry.axis is set) but the shared axes array is still empty. The radar DB needs axes registered first because reference-style entries must be reordered to match the axis order. Without axes there is no canonical ordering to map entries against, so the build aborts rather than emit silently-wrong data.

Source

Thrown at packages/mermaid/src/diagrams/radar/db.ts:82

const setCurves = (curves: Curve[]) => {
  data.curves = curves.map((curve) => {
    return {
      name: curve.name,
      label: curve.label ?? curve.name,
      entries: computeCurveEntries(curve.entries),
    };
  });
};

const computeCurveEntries = (entries: Entry[]): number[] => {
  // If entries have axis reference, we must order them according to the axes
  if (entries[0].axis == undefined) {
    return entries.map((entry) => entry.value);
  }
  const axes = getAxes();
  if (axes.length === 0) {
    throw new Error('Axes must be populated before curves for reference entries');
  }
  return axes.map((axis) => {
    const entry = entries.find((entry) => entry.axis?.$refText === axis.name);
    if (entry === undefined) {
      throw new Error('Missing entry for axis ' + axis.label);
    }
    return entry.value;
  });
};

const setOptions = (options: Option[]) => {
  // Create a map from option names to option objects for quick lookup
  const optionMap = options.reduce(
    (acc, option) => {
      acc[option.name] = option;
      return acc;
    },
    {} as Record<string, Option>

View on GitHub (pinned to d93e9c88c0)

Solutions

  1. Ensure the diagram text declares the `axis` block before the `curve` blocks (reference-mode entries require it).
  2. If calling the db directly, call db.setAxes(...) before db.setCurves(...).
  3. Switch curves to positional entries (drop the `axis <name>` reference) so ordering is taken from the entry list itself.
  4. Re-run db.clear() only once at the start and verify no second clear() runs between setAxes and setCurves.

Example fix

// before (broken order)
db.clear();
db.setCurves(curvesWithAxisRefs); // axes empty -> throws
db.setAxes(axes);

// after
db.clear();
db.setAxes(axes);
db.setCurves(curvesWithAxisRefs);
Defensive patterns

Strategy: validation

Validate before calling

// Before setCurves, ensure axes exist when entries use axis references
const usesRefs = curves.some(c => c.entries.length > 0 && c.entries[0].axis != null);
if (usesRefs && db.getAxes().length === 0) {
  throw new Error('Declare/parse axes before curves that reference them');
}
db.setCurves(curves);

Type guard

const isAxisRefEntry = (e): e is Entry & { axis: { $refText: string } } =>
  e != null && typeof e === 'object' && e.axis != null && typeof e.axis.$refText === 'string';

Try / catch

try {
  db.setCurves(curves);
} catch (e) {
  if (e instanceof Error && /Axes must be populated/.test(e.message)) {
    // ensure axes are set first, then retry once
    db.setAxes(axes);
    db.setCurves(curves);
  } else { throw e; }
}

Prevention

When it happens

Trigger: db.setCurves(curves) is invoked before db.setAxes(axes) AND at least one curve's first entry has an `axis` cross-reference ($refText). This normally cannot happen through the parser (it walks axes then curves) but can occur when calling the db API directly, with a hand-built AST, or after a parser/clear() ordering bug that resets data between the two calls.

Common situations: Embedding mermaid and driving the radar db programmatically out of order; partial diagram text where an `axis` block is missing or commented out but curves still use `axis <name>` references; a regression that swaps the populateDb visit order; tests that call setCurves in isolation.

Related errors


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