nats-io/nats-server · warning
gsl: nil channel
Error message
gsl: nil channel
What it means
ErrNilChan ('gsl: nil channel') is returned when registering a notification/interest watcher with a nil notification channel. registerNotification rejects a nil notify argument (server/sublist.go:174), and the identical sentinel also exists in the server's own sublist package (server/sublist.go:45) with the same message.
Source
Thrown at server/gsl/gsl.go:42
// interested subscribers. Subscribers can have wildcard subjects to
// match multiple published subjects.
// Common byte variables for wildcards and token separator.
const (
pwc = '*'
pwcs = "*"
fwc = '>'
fwcs = ">"
tsep = "."
btsep = '.'
_EMPTY_ = ""
)
// Sublist related errors
var (
ErrInvalidSubject = errors.New("gsl: invalid subject")
ErrNotFound = errors.New("gsl: no matches found")
ErrNilChan = errors.New("gsl: nil channel")
ErrAlreadyRegistered = errors.New("gsl: notification already registered")
)
// SimpleSublist is an alias type for GenericSublist that takes
// empty values, useful for tracking interest only without any
// unnecessary allocations.
type SimpleSublist = GenericSublist[struct{}]
// NewSimpleSublist will create a simple sublist.
func NewSimpleSublist() *SimpleSublist {
return &GenericSublist[struct{}]{root: newLevel[struct{}]()}
}
// A GenericSublist stores and efficiently retrieves subscriptions.
type GenericSublist[T comparable] struct {
sync.RWMutex
root *level[T]
count uint32View on GitHub (pinned to 3a66a489d2)
Solutions
- Create the notification channel (make(chan interface{}, size)) before registering the notification.
- Check for nil before calling registerNotification and return a clearer caller-side error.
- Unregister the old notification before nil-ing/replacing the channel rather than registering with a nil channel.
Example fix
// before
sl.Notify(n) // n.Chan is nil -> gsl: nil channel
// after
n.Chan = make(chan interface{}, 16)
if err := sl.Notify(n); err != nil {
return err
} Defensive patterns
Strategy: validation
Validate before calling
if n == nil || n.Chan == nil {
return errors.New("notification channel must be non-nil before registration")
} Try / catch
if err := sl.Notify(n); err != nil && errors.Is(err, gsl.ErrNilChan) {
return fmt.Errorf("create the notification channel first: %w", err)
} Prevention
- Always make() the channel before registering notifications.
- Unregister notifications before nil-ing channels in cleanup code.
- Add nil-channel checks in test helpers that construct notification objects.
When it happens
Trigger: Calling NewSublistNotification / notification registration APIs passing nil for the notification channel, e.g. a watcher created without a result channel or after the channel was closed and set to nil.
Common situations: Code paths where a results channel is lazily created but registration happens first, watch/interest tracking in tests passing nil, cleanup code nil-ing channels before unregistering notifications.
Related errors
- gsl: invalid subject
- gsl: no matches found
- account jwt not found
- auth callout violation: auth callout response is not for exp
- auth callout violation: auth callout response is not for ser
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/c1bd34aeb67c33a7.
Report an issue: GitHub.