d2lang/d2 · error

failed to unmarshal input edges graph to graph: %s

Error message

failed to unmarshal input edges graph to graph: %s

What it means

The plugin's RouteEdges RPC receives a serialized edges graph from the host process. d2graph.DeserializeGraph failed to decode in.GEdges into a d2graph.Graph, so the plugin cannot reconstruct the edges to route. This guards the plugin against malformed or incompatible serialized graph payloads.

Source

Thrown at d2plugin/serve.go:180

	inRaw, err := io.ReadAll(ms.Stdin)
	if err != nil {
		return err
	}

	var in routeEdgesInput
	err = json.Unmarshal(inRaw, &in)
	if err != nil {
		return err
	}

	var g d2graph.Graph
	if err := d2graph.DeserializeGraph(in.G, &g); err != nil {
		return fmt.Errorf("failed to unmarshal input graph to graph: %s", in)
	}

	var gedges d2graph.Graph
	if err := d2graph.DeserializeGraph(in.GEdges, &gedges); err != nil {
		return fmt.Errorf("failed to unmarshal input edges graph to graph: %s", in)
	}

	err = p.RouteEdges(ctx, &g, gedges.Edges)
	if err != nil {
		return err
	}

	b, err := d2graph.SerializeGraph(&g)
	if err != nil {
		return err
	}
	_, err = ms.Stdout.Write(b)
	if err != nil {
		return err
	}
	return nil
}

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Regenerate the GEdges payload with d2graph.SerializeGraph from the same d2 version as the plugin
  2. Verify the plugin and host use the same terrastruct/d2 module version (go.mod alignment)
  3. Inspect in.GEdges and confirm it is a valid serialized d2graph.Graph, not the DSL source or the main diagram
  4. If writing a custom caller, serialize the edges graph exactly as the d2 plugin host does

Example fix

// before
req.GEdges = string(diagramJSON) // wrong payload
// after
var gedges d2graph.Graph
gedges.Edges = g.Edges
b, _ := d2graph.SerializeGraph(&gedges)
req.GEdges = b
Defensive patterns

Strategy: validation

Validate before calling

var check d2graph.Graph
if err := d2graph.DeserializeGraph(in.GEdges, &check); err != nil {
	return fmt.Errorf("invalid GEdges payload: %w", err)
}

Prevention

When it happens

Trigger: Calling a routing plugin (via serve-handler) with an input whose GEdges field is not valid serialized d2graph JSON, or was produced by a different d2 version with an incompatible schema.

Common situations: Host and plugin built from different terrastruct/d2 versions; GEdges accidentally left nil/empty or overwritten with wrong JSON; custom plugin callers hand-constructing the request struct with an invalid GEdges blob.

Related errors


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