mermaid-js/mermaid · error

Group nodes can only have label. Remove the additional descr

Error message

Group nodes can only have label. Remove the additional description for node [${node.id}]

What it means

During state diagram finalize, each node's label array is split: index 0 becomes the label, the rest become the description. If the node is a composite/group (isGroup) and that leftover description is non-empty, mermaid throws because group nodes may carry only a label — extra text is ambiguous for the nested states.

Source

Thrown at packages/mermaid/src/diagrams/state/stateDb.ts:285

      undefined,
      this.getRootDocV2() as StateStmt,
      diagramStates,
      this.nodes,
      this.edges,
      true,
      config.look,
      this.classes
    );

    // Process node labels
    for (const node of this.nodes) {
      if (!Array.isArray(node.label)) {
        continue;
      }

      node.description = node.label.slice(1);
      if (node.isGroup && node.description.length > 0) {
        throw new Error(
          `Group nodes can only have label. Remove the additional description for node [${node.id}]`
        );
      }
      node.label = node.label[0];
    }
  }

  private handleStyleDef(item: StyleStmt) {
    const ids = item.id.trim().split(',');
    const styles = item.styleClass.split(',');

    for (const id of ids) {
      let state = this.getState(id);
      if (!state) {
        const trimmedId = id.trim();
        this.addState(trimmedId);
        state = this.getState(trimmedId);
      }

View on GitHub (pinned to d93e9c88c0)

Solutions

  1. Give the group node a single label only; move any extra text into a `note` or a child state.
  2. Split the multi-part label into the group label plus a `note left/right of <id>`.
  3. If the description belongs to a leaf, target that leaf state instead of the group.
  4. Check that code generation does not append descriptions to composite nodes.

Example fix

// before — composite state carries an extra description
state "Main\nSubtitle" as Main { [*] --> A }

// after
state Main { [*] --> A }
note right of Main : Subtitle
Defensive patterns

Strategy: validation

Validate before calling

// Reject composite states that carry extra label parts before rendering
for (const node of nodes) {
  if (node.isGroup && Array.isArray(node.label) && node.label.length > 1) {
    throw new Error(`Group ${node.id} may only have a single label`);
  }
}

Type guard

const isGroupLabelError = (e): boolean =>
  e instanceof Error && /Group nodes can only have label/.test(e.message);

Try / catch

try {
  await mermaid.run({ nodes: [el] });
} catch (e) {
  if (e instanceof Error && /Group nodes can only have label/.test(e.message)) {
    // move the extra text into a note or a child state
  } else { throw e; }
}

Prevention

When it happens

Trigger: Declaring a composite state with more than one string in its label, e.g. `state "X\nY" as S { ... }` or any group node receiving a multi-part label.

Common situations: Trying to annotate a composite state with a sub-caption; pasting a state definition that used a newline/colon separator inside a group; generated diagrams attaching descriptions to every node including composites.

Related errors


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