vitessio/vitess · error
nil not allowed
Error message
nil not allowed
What it means
stats.register installs a global variable hook (newVarHook) on a varGroup, and only one hook may ever exist per group. The library panics if the caller passes a nil hook function, since a nil hook would silently disable stats export and break the invariant that every registered var is delivered to the hook.
Source
Thrown at go/stats/export.go:87
const StatsAllStr = "all"
// NewVarHook is the type of a hook to export variables in a different way
type NewVarHook func(name string, v expvar.Var)
type varGroup struct {
sync.Mutex
vars map[string]expvar.Var
newVarHook NewVarHook
}
func (vg *varGroup) register(nvh NewVarHook) {
vg.Lock()
defer vg.Unlock()
if vg.newVarHook != nil {
panic("You've already registered a function")
}
if nvh == nil {
panic("nil not allowed")
}
vg.newVarHook = nvh
// Call hook on existing vars because some might have been
// created before the call to register
for k, v := range vg.vars {
nvh(k, v)
}
vg.vars = nil
}
func (vg *varGroup) publish(name string, v expvar.Var) {
if isVarDropped(name) {
return
}
vg.Lock()
defer vg.Unlock()
expvar.Publish(name, v)View on GitHub (pinned to 01a25a7d17)
Solutions
- Pass a non-nil function to stats.register, even a no-op like func(string, interface{}) {} if you do not need the values yet.
- Check the code path that builds the hook function and ensure it is assigned before register is called.
- Add an assert/unit test that the hook is non-nil before calling register to fail at the right place.
Example fix
// before
var hook func(string, interface{})
stats.register(hook) // panics: nil not allowed
// after
var hook func(string, interface{}) = func(_ string, _ interface{}) {}
stats.register(hook) Defensive patterns
Strategy: validation
Validate before calling
if hook == nil {
hook = func(string, interface{}) {} // or return an error before calling register
}
stats.register(hook) Prevention
- Never pass function variables that may be nil into registration APIs; initialize hooks at declaration.
- Add a unit test exercising the registration path on startup.
- Keep hook assignment and register call adjacent in the same init function.
When it happens
Trigger: Calling stats.register(nil) (or the package-level StatsCmdHook/Exporter registration wrappers with a nil function) before any hook has been set.
Common situations: A variable holding the hook function was not yet assigned when registration runs (initialization-order bug); a refactor removed the callback body leaving a nil func; wiring code conditionally skips assigning the hook in some build modes.
Related errors
- CountersWithMultiLabels: wrong number of values in Add
- CountersWithMultiLabels: wrong number of values in Reset
- GaugesWithMultiLabels: wrong number of values in Set
- You've already registered a function
- interval too small
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/075367e88ec0cbdc.
Report an issue: GitHub.