mermaid-js/mermaid · error

A same participant should only be defined in one Box: ${old.

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.

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)

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.