micro/go-micro · error

registry is required

Error message

registry is required

What it means

NewServer validates its Options before constructing the MCP gateway Server. Since the gateway relies entirely on the registry for service discovery and tool building, a nil Registry makes the server unusable, so construction fails immediately with "registry is required" instead of panicking later.

Source

Thrown at gateway/mcp/mcp.go:266

// NewServer creates an MCP gateway server from opts and starts service
// discovery and registry watching. It does not begin serving; call
// (*Server).Serve to start a transport and (*Server).Stop to shut down
// gracefully. This lets callers (e.g. the micro CLI) orchestrate the MCP
// gateway independently of any other gateway.
func NewServer(opts Options) (*Server, error) {
	// Set defaults
	if opts.Client == nil {
		opts.Client = client.DefaultClient
	}
	if opts.Context == nil {
		opts.Context = context.Background()
	}
	if opts.Logger == nil {
		opts.Logger = log.Default()
	}
	if opts.Registry == nil {
		return nil, fmt.Errorf("registry is required")
	}

	server := &Server{
		opts:     opts,
		tools:    make(map[string]*Tool),
		limiters: make(map[string]*rateLimiter),
		breakers: make(map[string]*circuitBreaker),
	}

	// Discover services and build tool list
	if err := server.discoverServices(); err != nil {
		return nil, fmt.Errorf("failed to discover services: %w", err)
	}

	// Watch for service changes
	go server.watchServices()

	return server, nil

View on GitHub (pinned to 24529f1404)

Solutions

  1. Set Options.Registry to a registry implementation, e.g. Registry: service.Options().Registry or Registry: registry.DefaultRegistry.
  2. If no service exists, explicitly construct one: reg := registry.NewRegistry(), then pass it in Options.
  3. For tests, pass a memory registry such as memory.NewRegistry().

Example fix

// before
srv, err := mcp.NewServer(mcp.Options{Address: ":3000"})
// after
srv, err := mcp.NewServer(mcp.Options{
    Registry: service.Options().Registry,
    Address:  ":3000",
})
Defensive patterns

Strategy: validation

Validate before calling

if opts.Registry == nil {
    return fmt.Errorf("mcp.Options.Registry must be set before calling NewServer")
}

Try / catch

srv, err := mcp.NewServer(opts)
if err != nil {
    log.Fatalf("mcp server init failed: %v", err)
}

Prevention

When it happens

Trigger: Calling mcp.NewServer (directly or via mcp.Serve/Run) with an Options struct where the Registry field is left as its zero value (nil), e.g. mcp.NewServer(mcp.Options{Address: ":3000"}) without setting Registry.

Common situations: Developers copy the doc example but forget to pass service.Options().Registry; constructing Options programmatically in tests; running the gateway in a binary that never initialized a go-micro service so no registry was available to pass.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/f7d8c5086975fc0b. Report an issue: GitHub.