gofr-dev/gofr · error
stream value could not be encoded
Error message
stream value could not be encoded
What it means
errStreamCorrupt is returned by writeFrame in pkg/gofr/http/stream.go when a value pulled from the stream source cannot be encoded into a stream frame. The stream is aborted rather than sending a malformed or partial frame to the client.
Source
Thrown at pkg/gofr/http/stream.go:21
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
resTypes "gofr.dev/pkg/gofr/http/response"
)
const (
defaultHeartbeat = 15 * time.Second
streamWriteWindow = 30 * time.Second
)
var (
errStreamPanic = errors.New("stream source panicked")
errNilStream = errors.New("stream source is nil")
errStreamCorrupt = errors.New("stream value could not be encoded")
)
// handleStream drains s.Source to the client, flushing after every write. It pulls values on
// demand so a slow client throttles the producer, sends a periodic keep-alive so a dropped client
// is detected while idle, bounds each write with a deadline, and always closes the source — leaving
// no goroutine behind when the client disconnects mid-stream. A Source that also honors its own
// context cancels promptly even without a heartbeat.
func (r Responder) handleStream(s resTypes.Stream) {
if s.Source == nil {
r.w.WriteHeader(http.StatusInternalServerError)
_, _ = r.w.Write([]byte(`{"error":{"message":"` + errNilStream.Error() + `"}}` + "\n"))
return
}
rc := http.NewResponseController(r.w)
setStreamHeaders(r.w, s.Format)View on GitHub (pinned to 187eb24962)
Solutions
- Make the streamed values encodable: use plain structs with exported fields and JSON-safe types
- Wrap or convert problematic values to encodable representations inside your Streamer before sending them on the channel
- Log the offending value to identify which item in the stream is corrupt
- Add a test streaming representative values end-to-end to catch encoding failures early
Example fix
// before
items <- func() {} // unencodable value -> errStreamCorrupt
// after
items <- map[string]string{"status": "ok"} // encodable value Defensive patterns
Strategy: type-guard
Validate before calling
func encodable(v any) error {
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
return fmt.Errorf("value of type %T is not encodable", v)
}
return nil
} Type guard
func isStreamCorrupt(err error) bool {
return errors.Is(err, errStreamCorrupt)
} Try / catch
err := streamValues(w, src)
if err != nil {
if errors.Is(err, errStreamCorrupt) {
log.Printf("dropping unencodable stream value: %v", err)
return errStreamingAborted
}
return err
} Prevention
- Stream only plain, exported-field structs and primitives
- Scrub values in the Streamer before pushing to the channel
- Add integration tests that encode representative values
- Avoid sending funcs, channels, or cyclic references in streams
When it happens
Trigger: A Streamer emits a value that the frame encoder cannot serialize (unsupported type, value containing channels/funcs/cyclic references) so writeFrame's encoding step fails and returns errStreamCorrupt.
Common situations: Streaming arbitrary Go values (e.g. structs with unexported fields the encoder rejects, or values that fail JSON-style marshaling); changing a streamed struct to include an unencodable field; emitting non-primitive types from a generic source.
Related errors
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/a2d4b908245f2563.
Report an issue: GitHub.