GoogleContainerTools/skaffold · error

starting HTTP server: %w

Error message

starting HTTP server: %w

What it means

server.Initialize wraps failures from newHTTPServer — which serves the HTTP variant of the Skaffold API and proxies to the gRPC port — as 'starting HTTP server: %w'. This happens after the gRPC server started successfully, when --rpc-http-port was requested and its listener could not be created.

Source

Thrown at pkg/skaffold/server/server.go:165

			logFileErr := event.SaveEventsToFile(opts.EventLogFile)
			if logFileErr != nil {
				errStr += fmt.Sprintf("event log file error: %s\n", logFileErr.Error())
			}

			v2EventLogFile := fmt.Sprintf(`%s.v2`, opts.EventLogFile)
			logFileV2Err := eventV2.SaveEventsToFile(v2EventLogFile)
			if logFileV2Err != nil {
				errStr += fmt.Sprintf("eventV2 log file error: %s\n", logFileV2Err.Error())
			}
		}

		// Save logs from current run to file
		eventV2.SaveLastLog(opts.LastLogFile)

		return errors.New(errStr)
	}
	if err != nil {
		return callback, fmt.Errorf("starting HTTP server: %w", err)
	}

	if opts.EnableRPC && opts.RPCPort.Value() == nil && opts.RPCHTTPPort.Value() == nil {
		log.Entry(context.TODO()).Warnf("started skaffold gRPC API on random port %d", grpcPort)
	}

	return callback, nil
}

func newGRPCServer(preferredPort int) (func() error, int, error) {
	l, port, err := listenPort(preferredPort)
	if err != nil {
		return func() error { return nil }, 0, fmt.Errorf("creating listener: %w", err)
	}

	log.Entry(context.TODO()).Infof("starting gRPC server on port %d", port)

	s := grpc.NewServer()

View on GitHub (pinned to a1189de023)

Solutions

  1. Free the HTTP port (lsof -i :PORT / ss -ltnp) and stop the conflicting process.
  2. Pick a different port via --rpc-http-port, or drop the flag entirely (skaffold then only runs the gRPC API on a chosen port).
  3. Note the gRPC server is already up when this fires: the returned shutdown callback will tear it down; simply retry after fixing the HTTP port.
  4. Ensure the port is unprivileged or the process has permission to bind it.

Example fix

// before
skaffold dev --rpc-http-port 50052 // in use

// after
skaffold dev --rpc-http-port 50053
# or omit the flag:
skaffold dev --rpc-port 50051
Defensive patterns

Strategy: retry

Validate before calling

if opts.RPCHTTPPort.Value() != nil {
	port := *opts.RPCHTTPPort.Value()
	l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
	if err != nil {
		return fmt.Errorf("http port %d unavailable: %w", port, err)
	}
	l.Close()
}

Try / catch

cb, err := server.Initialize(opts)
if err != nil && strings.Contains(err.Error(), "starting HTTP server") {
	// give up the fixed HTTP port and retry without it (gRPC API still available)
	opts.RPCHTTPPort = nil
	cb, err = server.Initialize(opts)
}
if err != nil {
	return err
}

Prevention

When it happens

Trigger: Calling Initialize(opts) with a non-nil opts.RPCHTTPPort and newHTTPServer(port, grpcPort) fails at listenPort: the requested HTTP port is occupied, privileged, or otherwise unbindable.

Common situations: Another skaffold run or an IDE plugin already holds the --rpc-http-port; the port collides with a locally running web server; container environments restricting port binding.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/4e42ed56ade12c4b. Report an issue: GitHub.