vitessio/vitess · error

You've already registered a function

Error message

You've already registered a function

What it means

stats.varGroup.register panics if a NewVarHook is registered more than once for the same var group. The hook is a process-wide singleton (e.g. stats.NewVarHook or package-level registration), so a second registration means two libraries are fighting over var creation callbacks. It also panics on a nil hook.

Source

Thrown at go/stats/export.go:84

}

// StatsAllStr is the consolidated name if a dimension gets combined.
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()

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Register the hook exactly once per process — guard with a sync.Once or a package-level 'registered' flag
  2. Check which package already registers the hook and remove or consolidate the duplicate registration
  3. In tests, reset/isolate via the stats package's test helpers instead of re-registering

Example fix

// before
stats.RegisterNewVarHook(hook) // called in two packages -> panics
// after
var once sync.Once
func registerHook() {
    once.Do(func() { stats.RegisterNewVarHook(hook) })
}
Defensive patterns

Strategy: validation

Validate before calling

var hookOnce sync.Once
func ensureHook() {
    hookOnce.Do(func() { stats.RegisterNewVarHook(hook) })
}

Prevention

When it happens

Trigger: Calling stats.RegisterNewVarHook (or vg.register) twice in one process, e.g. two packages/tests both installing a hook, or an init() that runs again due to duplicate wiring in tests.

Common situations: Test binaries importing multiple packages that each call the hook registration in init(); integrating a new observability library while an existing one already registered the hook; accidental double-invocation in setup code.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/c7e5232799f302e2. Report an issue: GitHub.