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

  1. Add a RouteEdges(ctx, *d2graph.Graph) ([][]int, error) method to the plugin type implementing RoutingPlugin
  2. Remove the routing feature from the plugin's Info if routing is not intended
  3. 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

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


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