d2lang/d2 · error
plugin has routing feature but does not implement RoutingPlu
Error message
plugin has routing feature but does not implement RoutingPlugin
What it means
When d2plugin serves a plugin process and receives the routeedges command, it asserts the plugin implements the RoutingPlugin interface. This error means the plugin declares the routing feature but its Go type does not implement RouteEdges.
Source
Thrown at d2plugin/serve.go:63
err = HydratePluginOpts(ctx, ms, p)
if err != nil {
return err
}
subcmd := ms.Opts.Flags.Arg(0)
switch subcmd {
case "info":
return info(ctx, p, ms)
case "flags":
return flags(ctx, p, ms)
case "layout":
return layout(ctx, p, ms)
case "postprocess":
return postProcess(ctx, p, ms)
case "routeedges":
routingPlugin, ok := p.(RoutingPlugin)
if !ok {
return fmt.Errorf("plugin has routing feature but does not implement RoutingPlugin")
}
return routeEdges(ctx, routingPlugin, ms)
default:
return xmain.UsageErrorf("unrecognized command: %s", subcmd)
}
}
}
func info(ctx context.Context, p Plugin, ms *xmain.State) error {
info, err := p.Info(ctx)
if err != nil {
return err
}
b, err := json.Marshal(info)
if err != nil {
return err
}
_, err = ms.Stdout.Write(b)View on GitHub (pinned to 0d69dca6f5)
Solutions
- Add a RouteEdges(ctx, *d2graph.Graph) ([][]int, error) method to the plugin type implementing RoutingPlugin
- Remove the routing feature from the plugin's Info if routing is not intended
- Embed or delegate to a RoutingPlugin implementation
Example fix
// before
func (p *myPlugin) Layout(ctx context.Context, g *d2graph.Graph) error { ... }
// after
func (p *myPlugin) RouteEdges(ctx context.Context, g *d2graph.Graph) ([][]int, error) { ... } // implement RoutingPlugin Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := p.(d2plugin.RoutingPlugin); !ok {
// don't advertise routing feature in Info()
} Type guard
rp, ok := p.(d2plugin.RoutingPlugin)
if !ok {
return fmt.Errorf("plugin does not implement RoutingPlugin")
}
_ = rp Try / catch
if err := runPluginServe(p); err != nil {
if strings.Contains(err.Error(), "does not implement RoutingPlugin") {
log.Fatal("fix plugin Info features or implement RouteEdges")
}
} Prevention
- Keep Info() features in sync with implemented interfaces
- Compile-time assertion: var _ d2plugin.RoutingPlugin = (*myPlugin)(nil)
- Test serving the plugin binary with each subcommand
When it happens
Trigger: Registering a plugin whose Info includes routing but whose plugin object only implements LayoutPlugin, then invoking the plugin binary with the routeedges subcommand.
Common situations: Custom plugin development: feature flags in Info() updated without extending the plugin type; copy-pasted plugin scaffolding missing the RouteEdges method.
Related errors
- plugin has routing feature but does not implement RoutingPlu
- failed to unmarshal input graph to graph: %s
- %v stderr: %s
- failed to unmarshal json: %w
- failed to unmarshal input to graph: %s
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/c888b609d4ad7321.
Report an issue: GitHub.