d2lang/d2 · error

Object "%s" has attribute "top" and/or "left" set, but layou

Error message

Object "%s" has attribute "top" and/or "left" set, but layout engine "%s" does not support locked positions. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.

What it means

FeatureSupportCheck verifies the selected layout engine supports the features actually used by the graph. This error is thrown when an object has top/left set (locked position) but the layout engine did not declare the TOP_LEFT feature.

Source

Thrown at d2plugin/plugin_features.go:41

// When this is true, the plugin also implements RoutingPlugin interface to route edges
const ROUTES_EDGES PluginFeature = "routes_edges"

func FeatureSupportCheck(info *PluginInfo, g *d2graph.Graph) error {
	// Older version of plugin. Skip checking.
	if info.Features == nil {
		return nil
	}

	featureMap := make(map[PluginFeature]struct{}, len(info.Features))
	for _, f := range info.Features {
		featureMap[f] = struct{}{}
	}

	for _, obj := range g.Objects {
		if obj.Top != nil || obj.Left != nil {
			if _, ok := featureMap[TOP_LEFT]; !ok {
				return fmt.Errorf(`Object "%s" has attribute "top" and/or "left" set, but layout engine "%s" does not support locked positions. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name)
			}
		}
		if (obj.WidthAttr != nil || obj.HeightAttr != nil) &&
			len(obj.ChildrenArray) > 0 && !obj.IsGridDiagram() {
			if _, ok := featureMap[CONTAINER_DIMENSIONS]; !ok {
				return fmt.Errorf(`Object "%s" has attribute "width" and/or "height" set, but layout engine "%s" does not support dimensions set on containers. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name)
			}
		}

		if obj.NearKey != nil {
			_, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey))
			if isKey {
				if _, ok := featureMap[NEAR_OBJECT]; !ok {
					return 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)
				}
			}
		}
	}

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Switch to a layout engine that supports locked positions (e.g. ELK)
  2. Remove the top/left attributes from the objects
  3. Pin the object near a constant value like near-top-center instead

Example fix

// before
x.near: top-left
// after
near-top-center: { near: top-center } // or switch to elk layout
Defensive patterns

Strategy: validation

Validate before calling

for _, obj := range g.Objects {
	if (obj.Top != nil || obj.Left != nil) && engineName != "elk" {
		// remove top/left or switch engine before layout
	}
}

Try / catch

if err := engine.FeatureSupportCheck(ctx, g); err != nil {
	return fmt.Errorf("layout feature unsupported: %w", err)
}

Prevention

When it happens

Trigger: A graph object has obj.Top or obj.Left set while the chosen layout engine's feature map lacks TOP_LEFT.

Common situations: Using a simple layout engine (e.g. dagre) after authoring a diagram for ELK with locked positions, or explicitly pinning x.y near/top/left with an unsupported engine.

Related errors


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