{"record":{"id":"2c7ebcb184782ce7","repo":"m1k1o/neko","slug":"listener-cannot-be-nil","errorCode":null,"errorMessage":"listener cannot be nil","messagePattern":"listener cannot be nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/capture/streamsink.go","lineNumber":215,"sourceCode":"\nfunc (manager *StreamSinkManagerCtx) removeListener(listener types.SampleListener) {\n\tptr := reflect.ValueOf(listener).Pointer()\n\n\tmanager.listenersMu.Lock()\n\tdelete(manager.listeners, ptr)\n\tdelete(manager.listenersKf, ptr) //\tif it's a keyframe listener, remove it too\n\tmanager.listenersMu.Unlock()\n\n\tmanager.logger.Debug().Interface(\"ptr\", ptr).Msgf(\"removing listener\")\n\tmanager.currentListeners.Set(float64(manager.ListenersCount()))\n}\n\nfunc (manager *StreamSinkManagerCtx) AddListener(listener types.SampleListener) error {\n\tmanager.mu.Lock()\n\tdefer manager.mu.Unlock()\n\n\tif listener == nil {\n\t\treturn errors.New(\"listener cannot be nil\")\n\t}\n\n\t// start if stopped\n\tif err := manager.start(); err != nil {\n\t\treturn err\n\t}\n\n\t// add listener\n\tmanager.addListener(listener)\n\n\treturn nil\n}\n\nfunc (manager *StreamSinkManagerCtx) RemoveListener(listener types.SampleListener) error {\n\tmanager.mu.Lock()\n\tdefer manager.mu.Unlock()\n\n\tif listener == nil {","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/m1k1o/neko/blob/b0f01cedea68893e85a3fd852c0521238c285695/server/internal/capture/streamsink.go#L197-L233","documentation":"StreamSinkManagerCtx.AddListener rejects a nil types.SampleListener with 'listener cannot be nil'. The library requires a concrete listener because it would later call its callback on each sample; a nil entry would panic at emit time. This is an input-validation guard.","triggerScenarios":"Calling AddListener(nil), or passing an uninitialized/zero-valued interface variable of types.SampleListener.","commonSituations":"Struct field holding the listener never assigned; a function parameter defaulted to nil; refactors where the concrete listener creation was removed but the call remained.","solutions":["Construct and pass a valid types.SampleListener implementation before calling AddListener","Guard call sites: only invoke AddListener when the listener variable is non-nil","Return an application-level error instead of adding when the listener is unavailable"],"exampleFix":"// before\nvar listener types.SampleListener\nmanager.AddListener(listener) // listener cannot be nil\n// after\nlistener := NewStreamListener()\nif listener != nil {\n    if err := manager.AddListener(listener); err != nil { return err }\n}","handlingStrategy":"validation","validationCode":"if listener == nil {\n    return errors.New(\"cannot add a nil stream listener\")\n}\nif err := manager.AddListener(listener); err != nil { return err }","typeGuard":"func listenerValid(l types.SampleListener) bool { return l != nil }","tryCatchPattern":"if err := manager.AddListener(listener); err != nil {\n    if err.Error() == \"listener cannot be nil\" {\n        return fmt.Errorf(\"listener not initialized: %w\", err)\n    }\n    return err\n}","preventionTips":["Initialize listener variables at declaration or constructor time","Never pass function parameters straight to AddListener without a nil check","Store added listeners so later Remove/Move calls have valid references","Run nil-check linting (e.g. staticcheck) on listener call sites"],"tags":["go","streamsink","nil-argument","validation"],"backgroundTag":"nil-argument-rejected","analyzedSha":"b0f01cedea68893e85a3fd852c0521238c285695","analyzedAt":"2026-09-01T10:35:56.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}