d2lang/d2 · error

invalid use of parent "_"

Error message

invalid use of parent "_"

What it means

A `_` (parent) token in a path is valid only when followed by at least one more identifier, e.g. `_.x`. A path that ends with `_` (nothing to resolve after going up a level) is meaningless, so resolution fails with this error.

Source

Thrown at d2graph/d2graph.go:810

			}
		}
	}

	resolvedObj = obj
	resolvedIDA = ida

	for i, id := range ida {
		if id != "_" {
			continue
		}
		if i != 0 && ida[i-1] != "_" {
			return nil, nil, errors.New(`parent "_" can only be used in the beginning of paths, e.g. "_.x"`)
		}
		if resolvedObj == obj.Graph.Root {
			return nil, nil, errors.New(`parent "_" cannot be used in the root scope`)
		}
		if i == len(ida)-1 {
			return nil, nil, errors.New(`invalid use of parent "_"`)
		}
		resolvedObj = resolvedObj.Parent
		resolvedIDA = resolvedIDA[1:]
	}

	return resolvedObj, resolvedIDA, nil
}

// TODO: remove edges []edge and scope each edge inside Object.
func (obj *Object) FindEdges(mk *d2ast.Key) ([]*Edge, bool) {
	if len(mk.Edges) != 1 {
		return nil, false
	}
	if mk.EdgeIndex.Int == nil {
		return nil, false
	}
	ae := mk.Edges[0]

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Add the target identifier after the `_`: write `_.child` instead of `_`.
  2. If you intended to reference the container itself, just use its name directly.
  3. Double-check generated/templated paths so no segment is dropped leaving a trailing `_`.

Example fix

// before
a._
// after
a._.child
Defensive patterns

Strategy: validation

Validate before calling

func pathNotEndingInParent(path string) bool {
  segs := strings.Split(path, ".")
  return segs[len(segs)-1] != "_"
}

Type guard

func lastSegmentIsTarget(ida []string) bool { return len(ida) > 0 && ida[len(ida)-1] != "_" }

Try / catch

if _, _, err := g.MiddlePath(obj, ida); err != nil && strings.Contains(err.Error(), `invalid use of parent`) {
  // append a missing target segment or strip the trailing _ before retrying
}

Prevention

When it happens

Trigger: Resolving a path whose last segment is `_`, such as `a._` or `_.`, via map key parsing or d2graph path resolution.

Common situations: Trailing underscore typos like `container._` when intending `container._.child`; generated paths where a final segment was dropped.

Related errors


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