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
- Register each key exactly once; audit init() functions for duplicate AdaptGetter calls for the same key
- If you need to re-register, use a new Viper instance or check ownership before adapting
- 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
- One registration per key; centralize all AdaptGetter calls
- Use LoadOrStore-style idempotent guards for package-level init registration
- Grep your codebase for duplicate key strings passed to AdaptGetter
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
- GetFuncForType does not support array types
- GetFuncForType does not support channel types
- GetFuncForType does not support function types
- GetFuncForType does not support interface types (specify a s
- no default GetFunc for type %T; call Configure with a custom
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/dd43a119e2549a77.
Report an issue: GitHub.