temporalio/temporal · error
duplicate registration of dynamic config key: %q
Error message
duplicate registration of dynamic config key: %q
What it means
register() enforces that each dynamic config Key is registered at most once; a second New*Setting call with the same key string panics. Duplicate keys would make queryRegistry ambiguous, so the failure is made loud at startup.
Source
Thrown at common/dynamicconfig/registry.go:28
settings map[Key]GenericSetting
queried atomic.Bool
}
)
var (
globalRegistry registry
)
func register(s GenericSetting) {
if globalRegistry.queried.Load() {
panic("dynamicconfig.New*Setting must only be called from static initializers")
}
if globalRegistry.settings == nil {
globalRegistry.settings = make(map[Key]GenericSetting)
}
if globalRegistry.settings[s.Key()] != nil {
// nolint:forbidigo // only called during static initialization
panic(fmt.Sprintf("duplicate registration of dynamic config key: %q", s.Key().String()))
}
globalRegistry.settings[s.Key()] = s
}
func queryRegistry(k Key) GenericSetting {
if !globalRegistry.queried.Load() {
globalRegistry.queried.Store(true)
}
return globalRegistry.settings[k]
}
// For testing only; do not call from regular code!
func ResetRegistryForTest() {
globalRegistry.settings = nil
globalRegistry.queried.Store(false)
}
View on GitHub (pinned to bde624efd1)
Solutions
- Rename one of the duplicate keys so each is unique (follow the component-prefix convention, e.g. matching., history.)
- Delete the redundant declaration if the setting already exists elsewhere
- Search the codebase for the key string before adding a new setting
Example fix
// before (two files)
var a = NewBoolSetting("matching.flag", false, ...)
var b = NewBoolSetting("matching.flag", true, ...)
// after
var a = NewBoolSetting("matching.flag", false, ...)
var b = NewBoolSetting("matching.otherFlag", true, ...) Defensive patterns
Strategy: validation
Validate before calling
// grep for key before adding
Prevention
- Unique prefixed keys
- Uniqueness tests
When it happens
Trigger: Two packages (or two vars in one package) declaring settings with the identical key string, e.g. two copies of NewBoolSetting("history.xxx", ...) after a copy-paste or a package split; tests declaring the same key in multiple files.
Common situations: Copy-pasting a setting declaration to a new file without renaming the key; merging branches that each added a setting with the same name; re-running declarations in test binaries sharing globals.
Related errors
- dynamicconfig.New*Setting must only be called from static in
- Can't deep copy non-zero time.Time: %v
- Can't deep copy value of type %s: %v
- ConvertGradualChange can only be used with scalar types for
- unsupported error type: %v
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/30bd0f48f306a141.
Report an issue: GitHub.