temporalio/temporal · error

stream not supported

Error message

stream not supported

What it means

errHTTPGRPCStreamNotSupported is returned by the HTTP API server's NewStream implementation: the Temporal HTTP API is a unary (POST/GET JSON) gateway over gRPC and does not support gRPC streaming. Any attempt to open a gRPC stream through the HTTP gateway fails with this error.

Source

Thrown at service/frontend/http_api_server.go:63

	serveMux                      *runtime.ServeMux
	stopped                       chan struct{}
	allowedHosts                  dynamicconfig.TypedPropertyFn[*regexp.Regexp]
	matchAdditionalHeaders        map[string]bool
	matchAdditionalHeaderPrefixes []string
}

var defaultForwardedHeaders = []string{
	"Authorization-Extras",
	"X-Forwarded-For",
	http.CanonicalHeaderKey(headers.ClientNameHeaderName),
	http.CanonicalHeaderKey(headers.ClientVersionHeaderName),
}

type httpRemoteAddrContextKey struct{}

var (
	errHTTPGRPCListenerNotTCP     = errors.New("must use TCP for gRPC listener to support HTTP API")
	errHTTPGRPCStreamNotSupported = errors.New("stream not supported")
)

// NewHTTPAPIServer creates an [HTTPAPIServer].
//
// routes registered with additionalRouteRegistrationFuncs take precedence over the auto generated grpc proxy routes.
func NewHTTPAPIServer(
	serviceConfig *Config,
	rpcConfig config.RPC,
	grpcListener net.Listener,
	tlsConfigProvider encryption.TLSConfigProvider,
	handler Handler,
	operatorHandler *OperatorHandlerImpl,
	interceptors []grpc.UnaryServerInterceptor,
	metricsHandler metrics.Handler,
	router *mux.Router,
	namespaceRegistry namespace.Registry,
	logger log.Logger,
) (*HTTPAPIServer, error) {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Use streaming RPCs against the native gRPC port (default 7233), not the HTTP API port (default 7243)
  2. Restructure the call as unary operations (polling) if you must stay on the HTTP API
  3. Check client configuration so SDK transport selection matches the endpoint type

Example fix

// before: client dials HTTP port for streaming
conn, _ := grpc.Dial("localhost:7243")
// after: use gRPC port
conn, _ := grpc.Dial("localhost:7233")
Defensive patterns

Strategy: fallback

Validate before calling

// check the method is unary before routing through the HTTP API
if methodKind(methodDesc) != grpc.UnaryCall {
    // route to native gRPC endpoint instead
}

Try / catch

if strings.Contains(err.Error(), "stream not supported") { // switch to gRPC port and retry as stream or poll as unary }

Prevention

When it happens

Trigger: An HTTP client or proxy invoking a streaming RPC method (gRPC server-streaming/bidi) against the HTTP API server, or a generated client attempting NewStream over the HTTP transport.

Common situations: Using grpc-gateway style clients expecting streaming, SDKs pointed at the HTTP port instead of the gRPC port, or workloads requiring long-lived streams (e.g. workflow task streams) misrouted through HTTP.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/7610aedeb1fe027a. Report an issue: GitHub.