{"record":{"id":"b1f6f2f186db7c28","repo":"d2lang/d2","slug":"failed-to-unmarshal-input-graph-to-graph-s","errorCode":null,"errorMessage":"failed to unmarshal input graph to graph: %s","messagePattern":"failed to unmarshal input graph to graph: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2plugin/serve.go","lineNumber":175,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc routeEdges(ctx context.Context, p RoutingPlugin, ms *xmain.State) error {\n\tinRaw, err := io.ReadAll(ms.Stdin)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar in routeEdgesInput\n\terr = json.Unmarshal(inRaw, &in)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar g d2graph.Graph\n\tif err := d2graph.DeserializeGraph(in.G, &g); err != nil {\n\t\treturn fmt.Errorf(\"failed to unmarshal input graph to graph: %s\", in)\n\t}\n\n\tvar gedges d2graph.Graph\n\tif err := d2graph.DeserializeGraph(in.GEdges, &gedges); err != nil {\n\t\treturn fmt.Errorf(\"failed to unmarshal input edges graph to graph: %s\", in)\n\t}\n\n\terr = p.RouteEdges(ctx, &g, gedges.Edges)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tb, err := d2graph.SerializeGraph(&g)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = ms.Stdout.Write(b)\n\tif err != nil {","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2plugin/serve.go#L157-L193","documentation":"In routeEdges of the served plugin, both the input graph (in.G) and the edges graph (in.GEdges) are deserialized. This error means in.G failed to deserialize into a d2graph.Graph.","triggerScenarios":"The routeedges RPC input's G field is empty, malformed, or not d2graph serialized JSON.","commonSituations":"Caller passing an unserialized graph, version skew between host and plugin changing serialization format, hand-crafted RPC payloads.","solutions":["Serialize the graph with d2graph.SerializeGraph before sending it as in.G","Check host/plugin d2 version compatibility","Dump in.G and validate it as JSON graph output"],"exampleFix":"// before\nin := RouteEdgesInput{G: rawGraphString}\n// after\nb, _ := d2graph.SerializeGraph(g)\nin := RouteEdgesInput{G: b}","handlingStrategy":"validation","validationCode":"var probe map[string]any\nif json.Unmarshal(in.G, &probe) != nil { /* in.G is not valid serialized graph JSON */ }","typeGuard":"func isValidRouteEdgesInput(in RouteEdgesInput) bool {\n\tvar g d2graph.Graph\n\treturn d2graph.DeserializeGraph(in.G, &g) == nil\n}","tryCatchPattern":"if err := routeEdges(ctx, p, ms); err != nil {\n\tif strings.Contains(err.Error(), \"failed to unmarshal input graph\") {\n\t\tlog.Printf(\"RouteEdgesInput.G was not a serialized d2 graph\")\n\t}\n}","preventionTips":["Serialize with d2graph.SerializeGraph before populating in.G","Validate RPC payloads in the caller before dispatch","Keep host and plugin on the same d2 version"],"tags":["plugin","json","deserialization","routing"],"backgroundTag":"plugin-input-invalid-json","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}