micro/go-micro · error

failed to register handlers: %w

Error message

failed to register handlers: %w

What it means

New wraps any error returned by the caller-provided opts.HandlerRegistrar while it registers HTTP handlers on the gateway's mux. The gateway itself cannot start without its handlers, so the registration failure aborts construction with this wrapped message.

Source

Thrown at gateway/api/gateway.go:72

		opts.Address = ":8080"
	}
	if opts.Context == nil {
		opts.Context = context.Background()
	}
	if opts.Logger == nil {
		opts.Logger = log.Default()
	}
	if opts.Registry == nil {
		opts.Registry = registry.DefaultRegistry
	}

	// Create a new mux for this gateway instance
	mux := http.NewServeMux()

	// Register handlers using the provided registrar
	if opts.HandlerRegistrar != nil {
		if err := opts.HandlerRegistrar(mux); err != nil {
			return nil, fmt.Errorf("failed to register handlers: %w", err)
		}
	}

	// Create HTTP server
	server := &http.Server{
		Addr:    opts.Address,
		Handler: mux,
	}

	gw := &Gateway{
		opts:   opts,
		server: server,
		mux:    mux,
	}

	// Start server in background
	go func() {
		opts.Logger.Printf("[gateway] Listening on %s (auth: %v)", opts.Address, opts.AuthEnabled)

View on GitHub (pinned to 24529f1404)

Solutions

  1. Inspect the wrapped (%w) inner error from your HandlerRegistrar; fix the underlying cause there.
  2. Validate all dependencies the registrar needs (config, clients) before calling New.
  3. Temporarily replace the registrar with a no-op to confirm the failure originates in your handler registration code.

Example fix

// before
registrar := func(mux *http.ServeMux) error { return svc.Handler() } // Handler may be nil
// after
if svc.Handler == nil { return errors.New("handler not initialized") }
registrar := func(mux *http.ServeMux) error { return svc.Handler() }
Defensive patterns

Strategy: try-catch

Validate before calling

if opts.HandlerRegistrar != nil {
    // dry-run against a throwaway mux to surface registration errors early
    if err := opts.HandlerRegistrar(http.NewServeMux()); err != nil {
        return fmt.Errorf("registrar failed pre-flight: %w", err)
    }
}

Try / catch

gw, err := api.New(cfg, opts)
if err != nil {
    var regErr error
    if strings.Contains(err.Error(), "failed to register handlers") {
        log.Fatalf("handler registrar failed: %v", errors.Unwrap(err))
    }
    return err
}

Prevention

When it happens

Trigger: Calling gateway/api.New (directly or via StartGateway/Run) with opts.HandlerRegistrar set to a function that returns an error, e.g. because one of the registered handlers panics-free checks fail or a dependency is missing.

Common situations: Custom registrar wiring routes that depend on an uninitialized service or bad config; a registrar that returns an error for a duplicate route pattern; nil dependencies captured by the registrar closure.

Related errors


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