mermaid-js/mermaid · error

A same participant should only be defined in one Box

Error message

A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${this.state.records.currentBox.name}' at the same time.

What it means

Inside sequence addActor(), when an actor id already exists and BOTH the existing record and the current pending context have a Box, and they are different Box objects, mermaid refuses to relocate the participant. A participant is allowed to live in only one Box, so the conflict is reported with both Box names.

Solutions

  1. Declare the participant in exactly one box and reference it elsewhere without re-declaring.
  2. Remove the earlier `participant Bob` (or its box) before re-declaring under a new box.
  3. Move all messages for that participant under the single box it belongs to.
  4. Use `AS` aliasing if you genuinely need two participants that share a display name in different boxes.

Example fix

// before
box A
  participant Bob
box B
  participant Bob  // conflict

// after — keep Bob in one box only
box A
  participant Bob
box B
  participant Bob2 as Bob
Defensive patterns

Strategy: validation

Validate before calling

// Track participant box ownership while building diagram text
const ownerBox = new Map();
function declare(box, id) {
  if (ownerBox.has(id) && ownerBox.get(id) !== box) {
    throw new Error(`${id} already in box ${ownerBox.get(id)}`);
  }
  ownerBox.set(id, box);
}

Type guard

const isBoxConflictError = (e): boolean =>
  e instanceof Error && /should only be defined in one Box/.test(e.message);

Try / catch

try {
  await mermaid.run({ nodes: [el] });
} catch (e) {
  if (e instanceof Error && /should only be defined in one Box/.test(e.message)) {
    // surface the two box names parsed from the message and ask the user to merge
  } else { throw e; }
}

Prevention

When it happens

Trigger: Defining `box A` then `participant Bob`, later opening `box B` and referencing `Bob` again (or declaring Bob inside box B); autolink/properties calls that re-add an existing participant while a different currentBox is active.

Common situations: Refactoring a sequence diagram and moving participants between boxes without removing the old declaration; large diagrams where the same actor is referenced from multiple sections each wrapped in a different box; autogenerated diagrams that emit redundant participant lines.

Related errors


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

Appendix: source

Thrown at packages/mermaid/src/diagrams/sequence/sequenceDb.ts:185

      if (!metadata.includes('\n')) {
        yamlData = '{\n' + metadata + '\n}';
      } else {
        yamlData = metadata + '\n';
      }
      doc = yaml.load(yamlData, { schema: yaml.JSON_SCHEMA }) as ParticipantMetaData;
    }
    type = doc?.type ?? type;

    // If alias is provided in metadata and description is not already set, use the alias
    if (doc?.alias && (!description || description.text === name)) {
      description = { text: doc.alias, wrap: description?.wrap, type };
    }

    const old = this.state.records.actors.get(id);
    if (old) {
      // If already set and trying to set to a new one throw error
      if (this.state.records.currentBox && old.box && this.state.records.currentBox !== old.box) {
        throw new Error(
          `A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${this.state.records.currentBox.name}' at the same time.`
        );
      }

      // Don't change the box if already
      assignedBox = old.box ? old.box : this.state.records.currentBox;
      old.box = assignedBox;

      // Don't allow description nulling
      if (old && name === old.name && description == null) {
        return;
      }
    }

    // Don't allow null descriptions, either
    if (description?.text == null) {
      description = { text: name, type };
    }

View on GitHub (pinned to d93e9c88c0)