{"record":{"id":"95d0f3f8fa6c0b11","repo":"d2lang/d2","slug":"connection-s-is-a-self-loop-on-a-container-but","errorCode":null,"errorMessage":"Connection \"%s\" is a self loop on a container, but layout engine \"%s\" does not support this. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.","messagePattern":"Connection \"(.+?)\" is a self loop on a container, but layout engine \"(.+?)\" does not support this\\. See https://d2lang\\.com/tour/layouts/#layout-specific-functionality for more\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2plugin/plugin_features.go","lineNumber":70,"sourceCode":"\t\t\t_, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey))\n\t\t\tif isKey {\n\t\t\t\tif _, ok := featureMap[NEAR_OBJECT]; !ok {\n\t\t\t\t\treturn fmt.Errorf(`Object \"%s\" has \"near\" set to another object, but layout engine \"%s\" only supports constant values for \"near\". See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif _, ok := featureMap[DESCENDANT_EDGES]; !ok {\n\t\tfor _, e := range g.Edges {\n\t\t\t// descendant edges are ok in sequence diagrams\n\t\t\tif e.Src.OuterSequenceDiagram() != nil || e.Dst.OuterSequenceDiagram() != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !e.Src.IsContainer() && !e.Dst.IsContainer() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif e.Src == e.Dst {\n\t\t\t\treturn fmt.Errorf(`Connection \"%s\" is a self loop on a container, but layout engine \"%s\" does not support this. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, e.AbsID(), info.Name)\n\t\t\t}\n\t\t\tif e.Src.IsDescendantOf(e.Dst) || e.Dst.IsDescendantOf(e.Src) {\n\t\t\t\treturn fmt.Errorf(`Connection \"%s\" goes from a container to a descendant, but layout engine \"%s\" does not support this. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, e.AbsID(), info.Name)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":52,"sourceCodeEnd":79,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2plugin/plugin_features.go#L52-L79","documentation":"FeatureSupportCheck rejects self-loop edges whose source and destination are the same container when the engine lacks DESCENDANT_EDGES support. Containers cannot loop to themselves in engines without this feature.","triggerScenarios":"An edge where e.Src == e.Dst and both are containers, and the layout engine's feature map lacks DESCENDANT_EDGES.","commonSituations":"Drawing a loop edge on a group/box containing children with dagre; diagrams authored against ELK reused with another engine.","solutions":["Switch to a layout engine supporting container self-loops (e.g. ELK)","Remove the self-loop edge on the container","Point the loop at a child object instead of the container"],"exampleFix":"// before\nc1.c1: { style.stroke: red }\n// after\nc1.a.c1.a // loop on a child, or use layout: elk","handlingStrategy":"validation","validationCode":"for _, e := range g.Edges {\n\tif e.Src == e.Dst && e.Src.IsContainer() && engineName != \"elk\" {\n\t\t// container self-loop unsupported; restructure\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err := engine.FeatureSupportCheck(ctx, g); err != nil {\n\treturn fmt.Errorf(\"container self-loop unsupported: %w\", err)\n}","preventionTips":["Don't self-loop containers with dagre","Attach loops to leaf objects instead","Prefer ELK for graphs with container loops"],"tags":["layout","feature-check","self-loop"],"backgroundTag":"layout-feature-unsupported","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}