googleapis/mcp-toolbox · critical

toolbox failed to start listener: %w

Error message

toolbox failed to start listener: %w

What it means

In runServe's non-TLS path, the server calls s.Listen(ctx, certFile, keyFile) to bind the address and serve. If the listener cannot start (port in use, permission denied, bad address), the error is wrapped with this message.

Source

Thrown at cmd/internal/serve/command.go:101

	protocol := "http"
	if useTLS {
		protocol = "https"
	}

	// run server in background
	srvErr := make(chan error, 1)
	if opts.Cfg.Stdio {
		go func() {
			defer close(srvErr)
			err = s.ServeStdio(ctx, opts.IOStreams.In, opts.IOStreams.Out)
			if err != nil {
				srvErr <- err
			}
		}()
	} else {
		err = s.Listen(ctx, opts.Cfg.CertFile, opts.Cfg.KeyFile)
		if err != nil {
			errMsg := fmt.Errorf("toolbox failed to start listener: %w", err)
			opts.Logger.ErrorContext(ctx, errMsg.Error())
			return errMsg
		}
		opts.Logger.InfoContext(ctx, "Server ready to serve!")
		if opts.Cfg.UI {
			opts.Logger.InfoContext(ctx, fmt.Sprintf("Toolbox UI is up and running at: %s://%s:%d/ui", protocol, opts.Cfg.Address, opts.Cfg.Port))
		}

		go func() {
			defer close(srvErr)
			err = s.Serve(ctx)
			if err != nil {
				srvErr <- err
			}
		}()
	}

	// wait for either the server to error out or the command's context to be canceled

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check for a process already bound to the port (lsof -i :5000) and stop it or change --port
  2. Choose an unprivileged port (>1024) if not running as root
  3. Verify the --address value resolves to a valid local interface
  4. Check container/K8s port mappings and security policies

Example fix

// before
./toolbox serve --port 80  // privileged
// after
./toolbox serve --port 5000
Defensive patterns

Strategy: validation

Validate before calling

// check the port is free before launching
if l, err := net.Listen("tcp", ":5000"); err != nil {
    log.Fatal("port 5000 already in use")
} else { l.Close() }

Try / catch

err = s.Listen(ctx, cfg.CertFile, cfg.KeyFile)
if err != nil {
    return fmt.Errorf("toolbox failed to start listener: %w", err)
}

Prevention

When it happens

Trigger: s.Listen returns an error: the configured address:port is already bound, the port is privileged (<1024) without permissions, or the address is invalid/unavailable.

Common situations: Another toolbox instance or service already listening on 5000 (the default port), running in a container without port mapping, or binding to an interface that doesn't exist.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/061769940642da39. Report an issue: GitHub.