dapr/dapr · error
Streaming unsupported!
Error message
Streaming unsupported!
What it means
FlushSSEResponse streams server-sent events by asserting the http.ResponseWriter implements http.Flusher; when it doesn't (a middleware wrapped the writer without forwarding Flush), it writes 500 'Streaming unsupported!' and returns nil — the error is deliberately swallowed, so callers see success while the client got a 500.
Source
Thrown at pkg/sse/sse.go:77
func HandleSSEGrpcResponse(res *invokev1.InvokeMethodResponse) error {
if res == nil {
return nil
}
statusOK := res.Status().GetCode() >= 200 && res.Status().GetCode() < 300
msg := "no response received from stream"
if statusOK {
msg = "no expected response from stream"
}
return status.Errorf(codes.Internal, messages.ErrChannelInvoke, errors.New(msg))
}
func FlushSSEResponse(ctx context.Context, writer http.ResponseWriter, reader io.Reader) error {
flusher, ok := writer.(http.Flusher)
if !ok {
http.Error(writer, "Streaming unsupported!", http.StatusInternalServerError)
return nil
}
// Add defer close for streaming case
closer, ok := reader.(io.Closer)
if ok {
defer closer.Close()
}
// Stream SSE data in real-time
buf := make([]byte, 1024)
for {
if err := ctx.Err(); err != nil {
return err
}
n, err := reader.Read(buf)
if n > 0 {View on GitHub (pinned to 74ad417027)
Solutions
- Make wrapper types implement Flush() by delegating to the underlying writer when it is an http.Flusher
- Move SSE routes outside the wrapping middleware chain
- In tests, decorate recorders with a Flush method or use writers that implement http.Flusher
Example fix
// before
type logWriter struct{ http.ResponseWriter }
// after
type logWriter struct {
http.ResponseWriter
}
func (l logWriter) Flush() {
if f, ok := l.ResponseWriter.(http.Flusher); ok {
f.Flush()
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// Wire the SSE route only through writers that can flush.
func supportsFlush(w http.ResponseWriter) (http.Flusher, bool) {
f, ok := w.(http.Flusher)
return f, ok
} Type guard
func canStreamSSE(w http.ResponseWriter) bool {
_, ok := w.(http.Flusher)
return ok
} Try / catch
if f, ok := w.(http.Flusher); ok {
f.Flush()
} else {
// degrade: buffer the response instead of streaming, or 501 with a clear error
http.Error(w, "streaming requires http.Flusher support", http.StatusNotImplemented)
} Prevention
- Give every ResponseWriter wrapper a delegating Flush() method
- Assert Flusher support in middleware unit tests that wrap streaming handlers
- Keep SSE routes outside compression/wrapping middleware chains
When it happens
Trigger: Invoking the SSE/grpc-proxy streaming path through a ResponseWriter wrapper (gzip, logging, metrics, custom auth middleware) whose concrete type lacks a Flush method; HTTP/1.0-style connections or test writers without flush support.
Common situations: Adding compression or observability middleware in front of handlers that wrap http.ResponseWriter and forget to delegate Flusher; unit tests using a custom recorder that does not implement Flush.
Related errors
- not implemented
- response does not contain the required fields in the leading
- response metadata found in non-leading chunk
- failed to proxy request: proxy not initialized. daprd startu
- failed to proxy request: proxy not initialized; daprd startu
AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16).
Data as JSON: /api/errors/b5c6cf6e58228f94.
Report an issue: GitHub.