vitessio/vitess · error

already adapted a getter for key

Error message

already adapted a getter for key 

What it means

AdaptGetter allows at most one getter per key per synchronized viper; the keys map tracks registrations. Registering the same key twice would leave two getters contending for one mutex slot, so it panics instead.

Source

Thrown at go/viperutil/internal/sync/sync.go:332

}

// end implementation of registry.Bindable for sync.Viper

// AdaptGetter wraps a get function (matching the signature of
// viperutil.Options.GetFunc) to be threadsafe with the passed-in synced Viper.
//
// It must be called prior to starting a watch on the synced Viper; it will
// panic if a watch has already been established.
//
// This function must be called at most once per key; it will panic if attempting
// to adapt multiple getters for the same key.
func AdaptGetter[T any](key string, getter func(v *viper.Viper) func(key string) T, v *Viper) func(key string) T {
	if v.watchingConfig {
		panic("cannot adapt getter to synchronized viper which is already watching a config")
	}

	if _, ok := v.keys[key]; ok {
		panic("already adapted a getter for key " + key)
	}

	var m sync.RWMutex
	v.keys[key] = &m

	return func(key string) T {
		m.RLock()
		defer m.RUnlock()

		return getter(v.live)(key)
	}
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Register each key exactly once; audit init() functions for duplicate AdaptGetter calls for the same key
  2. If you need to re-register, use a new Viper instance or check ownership before adapting
  3. Uniquify the key (e.g. prefix with package/feature name) if two components genuinely need distinct getters

Example fix

// before
sync.AdaptGetter[int]("pool_size", g, v)
sync.AdaptGetter[int]("pool_size", g2, v) // panics
// after
sync.AdaptGetter[int]("pool_size", g, v) // one registration per key
Defensive patterns

Strategy: validation

Validate before calling

var adapted sync.Map
func adaptOnce(key string, fn func()) { if _, ok := adapted.LoadOrStore(key, true); !ok { fn() } }

Prevention

When it happens

Trigger: Calling sync.AdaptGetter twice with the same key string on the same *Viper instance, e.g. duplicate registrations from two init() functions or two calls in a retry/loop.

Common situations: Two packages both register a getter for the same config key in their init(); accidentally re-running registration code on restart-in-process; copy-pasted registration lines.

Related errors


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