{"record":{"id":"6b8b68c0365ff868","repo":"d2lang/d2","slug":"could-not-find-center-of-s-is-it-declared-as-an","errorCode":null,"errorMessage":"could not find center of %s. Is it declared as an actor?","messagePattern":"could not find center of (.+?)\\. Is it declared as an actor\\?","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2layouts/d2sequence/sequence_diagram.go","lineNumber":605,"sourceCode":"\n// routeMessages routes horizontal edges (messages) from Src to Dst lifeline (actor/span center)\n// in another step, routes are adjusted to spans borders when necessary\nfunc (sd *sequenceDiagram) routeMessages() error {\n\tmessageOffset := sd.maxActorHeight + sd.yStep\n\tfor _, message := range sd.messages {\n\t\tmessage.ZIndex = MESSAGE_Z_INDEX\n\t\tnoteOffset := 0.\n\t\tfor _, note := range sd.notes {\n\t\t\tif sd.verticalIndices[note.AbsID()] < sd.verticalIndices[message.AbsID()] {\n\t\t\t\tnoteOffset += note.Height + sd.yStep\n\t\t\t}\n\t\t}\n\n\t\tvar startX, endX float64\n\t\tif startCenter := getCenter(message.Src); startCenter != nil {\n\t\t\tstartX = startCenter.X\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"could not find center of %s. Is it declared as an actor?\", message.Src.ID)\n\t\t}\n\t\tif endCenter := getCenter(message.Dst); endCenter != nil {\n\t\t\tendX = endCenter.X\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"could not find center of %s. Is it declared as an actor?\", message.Dst.ID)\n\t\t}\n\t\tisToDescendant := strings.HasPrefix(message.Dst.AbsID(), message.Src.AbsID()+\".\")\n\t\tisFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()+\".\")\n\t\tisSelfMessage := message.Src == message.Dst\n\n\t\tcurrSrc := message.Src\n\t\tfor !currSrc.Parent.IsSequenceDiagram() {\n\t\t\tcurrSrc = currSrc.Parent\n\t\t}\n\t\tcurrDst := message.Dst\n\t\tfor !currDst.Parent.IsSequenceDiagram() {\n\t\t\tcurrDst = currDst.Parent\n\t\t}","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2layouts/d2sequence/sequence_diagram.go#L587-L623","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nouter.shape -> b\n// after\nouter -> b","handlingStrategy":"validation","validationCode":"for _, msg := range messages {\n\tif !isDeclaredActor(msg.Src) {\n\t\treturn fmt.Errorf(\"source %s must be a declared actor\", msg.Src.AbsID())\n\t}\n}","typeGuard":"func isDeclaredActor(obj *d2graph.Object) bool {\n\treturn obj != nil && obj.Parent != nil && obj.Parent.IsSequenceDiagram()\n}","tryCatchPattern":"if err := layout(...); err != nil {\n\tif strings.Contains(err.Error(), \"Is it declared as an actor?\") {\n\t\treturn fmt.Errorf(\"check sequence endpoints: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["d2","sequence-diagram","actor","layout"],"backgroundTag":"actor-center-not-found","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}