{"record":{"id":"c67ef056441d2d46","repo":"gofr-dev/gofr","slug":"stream-source-panicked","errorCode":null,"errorMessage":"stream source panicked","messagePattern":"stream source panicked","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/http/stream.go","lineNumber":19,"sourceCode":"package http\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\tresTypes \"gofr.dev/pkg/gofr/http/response\"\n)\n\nconst (\n\tdefaultHeartbeat  = 15 * time.Second\n\tstreamWriteWindow = 30 * time.Second\n)\n\nvar (\n\terrStreamPanic   = errors.New(\"stream source panicked\")\n\terrNilStream     = errors.New(\"stream source is nil\")\n\terrStreamCorrupt = errors.New(\"stream value could not be encoded\")\n)\n\n// handleStream drains s.Source to the client, flushing after every write. It pulls values on\n// demand so a slow client throttles the producer, sends a periodic keep-alive so a dropped client\n// is detected while idle, bounds each write with a deadline, and always closes the source — leaving\n// no goroutine behind when the client disconnects mid-stream. A Source that also honors its own\n// context cancels promptly even without a heartbeat.\nfunc (r Responder) handleStream(s resTypes.Stream) {\n\tif s.Source == nil {\n\t\tr.w.WriteHeader(http.StatusInternalServerError)\n\t\t_, _ = r.w.Write([]byte(`{\"error\":{\"message\":\"` + errNilStream.Error() + `\"}}` + \"\\n\"))\n\n\t\treturn\n\t}\n\n\trc := http.NewResponseController(r.w)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/http/stream.go#L1-L37","documentation":"errStreamPanic is declared in pkg/gofr/http/stream.go and signals that the Streamer source backing an HTTP stream panicked during execution. The streaming machinery recovers the panic (see readStream) and converts it into this error so the client connection is terminated cleanly instead of crashing the process.","triggerScenarios":"A user-supplied resTypes.Streamer source panics (nil map write, index out of range, explicit panic) while readStream is pulling values; the recovered panic is wrapped as '%w: %v' with errStreamPanic and sent over the terminal error channel.","commonSituations":"Buggy custom stream generators (nil pointer dereference on business objects); sources that panic on channel close; data-dependent panics mid-stream such as division by zero or type assertions on unexpected values.","solutions":["Find the panic value in the wrapped error message ('stream source panicked: <p>') to locate the faulting code","Fix the underlying panic in your Streamer implementation","Add defensive checks (nil guards, bounds checks) inside the source before it produces values","Recover and convert expected failure modes into ordinary errors inside your source instead of panicking"],"exampleFix":"// before\nfunc (s *mySource) Stream(items chan<- any) {\n    for _, v := range s.data { // panics if s.data is nil\n        items <- v\n    }\n}\n// after\nfunc (s *mySource) Stream(items chan<- any) {\n    if s.data == nil {\n        return\n    }\n    for _, v := range s.data {\n        items <- v\n    }\n}","handlingStrategy":"try-catch","validationCode":"if source == nil {\n    return errors.New(\"stream source must not be nil\")\n}\nif err := source.Validate(); err != nil {\n    return err\n}","typeGuard":"func hasValidSource(s *Stream) bool {\n    return s != nil && s.Source != nil && !reflect.ValueOf(s.Source).IsNil()\n}","tryCatchPattern":"err := runStream(ctx, src)\nif err != nil {\n    if errors.Is(err, errStreamPanic) {\n        log.Printf(\"stream source panicked: %v\", err)\n        reconnectOrFallback(ctx)\n        return\n    }\n    return err\n}","preventionTips":["Never panic inside Streamer implementations; return errors instead","Guard nil maps/slices and type assertions in source loops","Test sources with edge-case data (nil fields, empty inputs)","Keep the panic value from the wrapped error for diagnostics"],"tags":["streaming","panic","recovery"],"backgroundTag":"stream-source-panic","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}