d2lang/d2 · error

actors in sequence diagrams cannot themselves be sequence di

Error message

actors in sequence diagrams cannot themselves be sequence diagrams: %s

What it means

While building a sequence diagram's actor list, newSequenceDiagram walks the graph and if an actor object is itself a sequence diagram, the layout cannot be computed. The error reports the offending actor's absolute ID.

Source

Thrown at d2layouts/d2sequence/sequence_diagram.go:103

	slices.SortFunc(messages, func(a, b *d2graph.Edge) int {
		return cmp.Compare(getEdgeEarliestLineNum(a), getEdgeEarliestLineNum(b))
	})

	for _, obj := range objects {
		if obj.IsSequenceDiagramGroup() {
			queue := []*d2graph.Object{obj}
			// Groups may have more nested groups
			for len(queue) > 0 {
				curr := queue[0]
				curr.LabelPosition = go2.Pointer(label.InsideTopLeft.String())
				groups = append(groups, curr)
				queue = queue[1:]
				queue = append(queue, curr.ChildrenArray...)
			}
		} else {
			actors = append(actors, obj)
			if obj.IsSequenceDiagram() {
				return nil, fmt.Errorf("actors in sequence diagrams cannot themselves be sequence diagrams: %s", obj.AbsID())
			}
		}
	}

	if len(actors) == 0 {
		return nil, errors.New("no actors declared in sequence diagram")
	}

	sd := &sequenceDiagram{
		messages:        messages,
		actors:          actors,
		groups:          groups,
		spans:           nil,
		notes:           nil,
		lifelines:       nil,
		objectRank:      make(map[*d2graph.Object]int),
		firstMessage:    make(map[*d2graph.Object]*d2graph.Edge),
		lastMessage:     make(map[*d2graph.Object]*d2graph.Edge),

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Move the inner sequence diagram out of the actor list (make it a sibling, not a child of an actor)
  2. Convert the inner sequence diagram to a plain shape or a separate board
  3. Flatten the nesting by declaring the messages between top-level actors instead

Example fix

// before
x: shape sequence_diagram {
  y -> z
}
x.y -> x.z
// after
x: shape sequence_diagram
y: shape sequence_diagram { a -> b }
Defensive patterns

Strategy: validation

Validate before calling

for _, actor := range actors {
	if actor.IsSequenceDiagram() {
		return fmt.Errorf("actor %s is itself a sequence diagram", actor.AbsID())
	}
}

Try / catch

_, err := d2lib.Compile(ctx, input, opts)
if err != nil && strings.Contains(err.Error(), "cannot themselves be sequence diagrams") {
	return fmt.Errorf("invalid nesting: %w", err)
}

Prevention

When it happens

Trigger: Declaring a nested sequence diagram (a board/shape with inner children that form a sequence diagram) inside the actors of another sequence diagram in a D2 script, then running layoutSequenceDiagram.

Common situations: Authoring D2 diagrams where a sequence diagram's participant shape is itself given sequence-diagram children (actor-in-actor nesting); accidental indentation creating nested sequence blocks.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/aacbdd97754089bc. Report an issue: GitHub.