gofr-dev/gofr · error
stream source is nil
Error message
stream source is nil
What it means
errNilStream is declared in pkg/gofr/http/stream.go and indicates the Streamer source supplied to the streaming endpoint is nil. The framework cannot drain a nil source, so it refuses to start the stream rather than panicking later.
Source
Thrown at pkg/gofr/http/stream.go:20
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)
View on GitHub (pinned to 187eb24962)
Solutions
- Ensure the code path that builds the Streamer always returns a valid implementation
- Check and handle the error from your source factory before handing the source to the stream
- Treat typed-nil pointers (e.g. (*mySource)(nil)) as invalid and return a real error instead
- Add a unit test asserting the stream setup fails fast when the source is absent
Example fix
// before
src, _ := NewSource(cfg)
handleStream(src) // src may be nil -> errNilStream
// after
src, err := NewSource(cfg)
if err != nil {
return err
}
if src == nil {
return errors.New("no stream source configured")
}
handleStream(src) Defensive patterns
Strategy: validation
Validate before calling
func ensureSource(src resTypes.Streamer) error {
if src == nil {
return errors.New("stream source is nil")
}
return nil
} Type guard
func isNilStreamer(v any) bool {
if v == nil { return true }
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr, reflect.Interface, reflect.Func:
return rv.IsNil()
}
return false
} Try / catch
if err := startStream(src); err != nil {
if errors.Is(err, errNilStream) {
log.Printf("no stream source configured: %v", err)
return ErrNoSource
}
return err
} Prevention
- Always check the error from source constructors before use
- Avoid typed-nil returns (return nil, err not &T{}, err)
- Default-fill source configuration instead of leaving it unset
- Unit-test stream setup paths where config is missing
When it happens
Trigger: Passing a nil Streamer (or a typed-nil pointer) as the source when setting up a streaming response, so handleStream/readStream detect there is nothing to drain.
Common situations: Constructing a stream source conditionally and leaving the nil case unhandled; a factory function returning nil on error whose error is ignored; JSON/config-driven source selection defaulting to nil.
Related errors
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/d8e94d80e1e21b4f.
Report an issue: GitHub.