{"record":{"id":"2763f425450c7d0d","repo":"d2lang/d2","slug":"plugin-has-routing-feature-but-does-not-implement","errorCode":null,"errorMessage":"plugin has routing feature but does not implement RoutingPlugin","messagePattern":"plugin has routing feature but does not implement RoutingPlugin","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2cli/main.go","lineNumber":481,"sourceCode":"\t\t}\n\n\t\tpluginInfo, err := plugin.Info(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\thasRouter := false\n\t\tfor _, feat := range pluginInfo.Features {\n\t\t\tif feat == d2plugin.ROUTES_EDGES {\n\t\t\t\thasRouter = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !hasRouter {\n\t\t\treturn nil, nil\n\t\t}\n\t\troutingPlugin, ok := plugin.(d2plugin.RoutingPlugin)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"plugin has routing feature but does not implement RoutingPlugin\")\n\t\t}\n\n\t\trouteEdges := d2graph.RouteEdges(routingPlugin.RouteEdges)\n\t\tcached[engine] = routeEdges\n\t\treturn routeEdges, nil\n\t}\n}\n\nfunc compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs fs.FS, layout *string, renderOpts d2svg.RenderOpts, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily, animateInterval int64, inputPath, outputPath string, boardPath []string, noChildren, bundle, forceAppendix bool, browser playwright.Browser, ext exportExtension, asciiMode string) (_ []byte, written bool, _ error) {\n\t// Use ELK layout for ascii outputs when layout is dagre or unspecified\n\tif ext == TXT {\n\t\tif layout == nil || *layout == \"dagre\" {\n\t\t\tif ms.Log.Debug != nil {\n\t\t\t\tprevLayout := \"unspecified\"\n\t\t\t\tif layout != nil {\n\t\t\t\t\tprevLayout = *layout\n\t\t\t\t}\n\t\t\t\tms.Log.Debug.Printf(\"switching layout engine to ELK for ASCII format (was %s)\", prevLayout)","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2cli/main.go#L463-L499","documentation":"The engine resolver checks that a plugin advertising the routing feature actually implements the d2plugin.RoutingPlugin interface. A plugin that claims hasRouter but fails the type assertion cannot satisfy route requests, so Run returns this error.","triggerScenarios":"Requesting an engine whose plugin reports the routing capability but whose concrete type does not implement RoutingPlugin — i.e. a misregistered/incompatible custom plugin.","commonSituations":"Custom or third-party layout plugins that enable the routing feature flag without implementing RouteEdges, or version mismatches between plugin and d2 versions.","solutions":["Update the plugin to implement d2plugin.RoutingPlugin including RouteEdges","Use a different engine that fully implements the routing feature","Fix plugin registration so the routing feature flag is not set unless the interface is implemented"],"exampleFix":"// before\ntype MyPlugin struct{} // has routing feature flag but no RouteEdges\n// after\nfunc (p *MyPlugin) RouteEdges(g *d2graph.Graph) error { /* ... */ return nil } // implement RoutingPlugin","handlingStrategy":"type-guard","validationCode":"if rp, ok := plugin.(d2plugin.RoutingPlugin); !ok {\n    // reject or disable routing feature for this plugin before use\n}","typeGuard":"func supportsRouting(p d2plugin.Plugin) bool {\n    _, ok := p.(d2plugin.RoutingPlugin)\n    return ok\n}","tryCatchPattern":"router, err := LayoutResolver(ctx, ms, plugins)(engine)\nif err != nil {\n    // fall back to a known-good engine that implements RoutingPlugin\n}","preventionTips":["Only enable the routing feature flag on plugins implementing RoutingPlugin","Add an interface-assertion check at plugin registration time (var _ d2plugin.RoutingPlugin = (*P)(nil))","Keep plugin and d2 versions in sync"],"tags":["go","plugin","interface","type-assertion"],"backgroundTag":"plugin-interface-not-implemented","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}