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
- Regenerate the GEdges payload with d2graph.SerializeGraph from the same d2 version as the plugin
- Verify the plugin and host use the same terrastruct/d2 module version (go.mod alignment)
- Inspect in.GEdges and confirm it is a valid serialized d2graph.Graph, not the DSL source or the main diagram
- 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
- Keep host and plugin on the same terrastruct/d2 version
- Always produce GEdges with d2graph.SerializeGraph
- Never hand-construct plugin request payloads
- Add a smoke test that round-trips Serialize/DeserializeGraph
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
- failed to unmarshal input to graph: %s
- failed to unmarshal input graph to graph: %s
- plugin has routing feature but does not implement RoutingPlu
- %v stderr: %s
- failed to unmarshal json: %w
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/cd1f417ee403f0ad.
Report an issue: GitHub.