d2lang/d2 · error
could not find center of %s. Is it declared as an actor?
Error message
could not find center of %s. Is it declared as an actor?
What it means
routeMessages needs the horizontal center X of each message endpoint to draw the sequence lifeline arrows. getCenter returned nil for the message's Src, meaning that object has no computed center — typically because it was never registered as an actor.
Source
Thrown at d2layouts/d2sequence/sequence_diagram.go:605
// routeMessages routes horizontal edges (messages) from Src to Dst lifeline (actor/span center)
// in another step, routes are adjusted to spans borders when necessary
func (sd *sequenceDiagram) routeMessages() error {
messageOffset := sd.maxActorHeight + sd.yStep
for _, message := range sd.messages {
message.ZIndex = MESSAGE_Z_INDEX
noteOffset := 0.
for _, note := range sd.notes {
if sd.verticalIndices[note.AbsID()] < sd.verticalIndices[message.AbsID()] {
noteOffset += note.Height + sd.yStep
}
}
var startX, endX float64
if startCenter := getCenter(message.Src); startCenter != nil {
startX = startCenter.X
} else {
return fmt.Errorf("could not find center of %s. Is it declared as an actor?", message.Src.ID)
}
if endCenter := getCenter(message.Dst); endCenter != nil {
endX = endCenter.X
} else {
return fmt.Errorf("could not find center of %s. Is it declared as an actor?", message.Dst.ID)
}
isToDescendant := strings.HasPrefix(message.Dst.AbsID(), message.Src.AbsID()+".")
isFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()+".")
isSelfMessage := message.Src == message.Dst
currSrc := message.Src
for !currSrc.Parent.IsSequenceDiagram() {
currSrc = currSrc.Parent
}
currDst := message.Dst
for !currDst.Parent.IsSequenceDiagram() {
currDst = currDst.Parent
}View on GitHub (pinned to 0d69dca6f5)
Solutions
- Declare the source endpoint as a top-level actor in the sequence diagram
- Move the message endpoint to an actor shape instead of a nested child
- Check for typos in the edge's source key so it matches a declared actor
- Reproduce with the object's AbsID to confirm which shape is missing
Example fix
// before outer.shape -> b // after outer -> b
Defensive patterns
Strategy: validation
Validate before calling
for _, msg := range messages {
if !isDeclaredActor(msg.Src) {
return fmt.Errorf("source %s must be a declared actor", msg.Src.AbsID())
}
} Type guard
func isDeclaredActor(obj *d2graph.Object) bool {
return obj != nil && obj.Parent != nil && obj.Parent.IsSequenceDiagram()
} Try / catch
if err := layout(...); err != nil {
if strings.Contains(err.Error(), "Is it declared as an actor?") {
return fmt.Errorf("check sequence endpoints: %w", err)
}
return err
} Prevention
- Connect only top-level actors in sequence diagrams, not their children
- Verify edge keys match declared actor AbsIDs exactly
- Retarget edges to the containing actor when messaging into groups
When it happens
Trigger: A message (edge) in the sequence diagram references a Src object that getCenter cannot find among laid-out actors — e.g. the source is a child/descendant shape not added as an actor during the walk.
Common situations: Connecting to a shape that lives inside a group/box rather than a top-level actor; messages referencing shapes declared after layout skipped them; typos causing the Src key to resolve to an unexpected object.
Related errors
- no actors declared in sequence diagram
- no available layout
- dimensions for object label %#v not found
- actors in sequence diagrams cannot themselves be sequence di
- no layout resolver configured for layout engine %q
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/6b8b68c0365ff868.
Report an issue: GitHub.