jaegertracing/jaeger · critical

query server failed to initialize listener: %w

Error message

query server failed to initialize listener: %w

What it means

Server.Start brings up both the HTTP and gRPC query servers, and it first calls initListener to bind the configured ports. If the listener cannot be created — the OS refuses the bind — Start returns this wrapped error immediately so the extension fails fast instead of serving on a broken socket.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/server.go:459

	}

	s.httpConn, err = s.queryOptions.HTTP.ToListener(ctx)
	if err != nil {
		return err
	}
	s.telset.Logger.Info(
		"Query server started",
		zap.String("http_addr", s.HTTPAddr()),
		zap.String("grpc_addr", s.GRPCAddr()),
	)
	return nil
}

// Start http and gRPC servers concurrently
func (s *Server) Start(ctx context.Context) error {
	err := s.initListener(ctx)
	if err != nil {
		return fmt.Errorf("query server failed to initialize listener: %w", err)
	}

	var httpPort int
	if port, err := getPortForAddr(s.httpConn.Addr()); err == nil {
		httpPort = port
	}

	var grpcPort int
	if port, err := getPortForAddr(s.grpcConn.Addr()); err == nil {
		grpcPort = port
	}

	s.bgFinished.Go(func() {
		s.telset.Logger.Info("Starting HTTP server", zap.Int("port", httpPort), zap.String("addr", s.queryOptions.HTTP.NetAddr.Endpoint))
		err := s.httpServer.Serve(s.httpConn)
		if err != nil && !errors.Is(err, http.ErrServerClosed) {
			s.telset.Logger.Error("Could not start HTTP server", zap.Error(err))
			s.telset.ReportStatus(componentstatus.NewFatalErrorEvent(err))

View on GitHub (pinned to 806f444784)

Solutions

  1. Check the wrapped inner error: 'address already in use' means find and stop the other process (lsof -i :16686) or change --query.http-server / grpc-server ports
  2. Verify the configured port values in the config file/flags are valid numbers within 1-65535 and the host address is resolvable
  3. If binding a privileged port, run with the required capability or move to an unprivileged port
  4. Wait for a previous instance to fully shut down (Close releases the listener) before starting a new one on the same ports

Example fix

// before: port already taken by a stale process
jaeger-query --query.http-server.host-port=:16686  # Error: listen tcp :16686: bind: address already in use
// after
kill <stale-pid> && jaeger-query --query.http-server.host-port=:16686
Defensive patterns

Strategy: retry

Validate before calling

// check the port is free before starting the server
func portFree(addr string) bool {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return false
	}
	ln.Close()
	return true
}

Try / catch

err := server.Start(ctx)
if err != nil {
	if errors.Is(err, syscall.EADDRINUSE) || strings.Contains(err.Error(), "address already in use") {
		// pick another port or abort startup with a clear message
		log.Fatalf("query port already in use: %v", err)
	}
	return fmt.Errorf("starting query server: %w", err)
}

Prevention

When it happens

Trigger: Calling Server.Start (via the extension's Start) when initListener fails: the configured HTTP/gRPC port is already bound by another process, the port number is out of the valid range (e.g. 0 not allowed for this listener, or > 65535), or the process lacks permission to bind (privileged port without capabilities).

Common situations: Two jaeger-query instances pointed at the same ports; a leftover development process still holding port 16686/16685; docker port-mapping conflicts; config where the port was left blank or mistyped so it resolves to an invalid address; running in a container as non-root while binding port < 1024.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/c042c81a012afd5a. Report an issue: GitHub.