uber-go/zap · error
encoder already registered for name %q
Error message
encoder already registered for name %q
What it means
RegisterEncoder stores constructors in a global name→constructor map and rejects duplicate registration with fmt.Errorf("encoder already registered for name %q", name) to prevent accidental overwriting of an existing encoder.
Source
Thrown at encoder.go:58
},
}
_encoderMutex sync.RWMutex
)
// RegisterEncoder registers an encoder constructor, which the Config struct
// can then reference. By default, the "json" and "console" encoders are
// registered.
//
// Attempting to register an encoder whose name is already taken returns an
// error.
func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error {
_encoderMutex.Lock()
defer _encoderMutex.Unlock()
if name == "" {
return errNoEncoderNameSpecified
}
if _, ok := _encoderNameToConstructor[name]; ok {
return fmt.Errorf("encoder already registered for name %q", name)
}
_encoderNameToConstructor[name] = constructor
return nil
}
func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil {
return nil, errors.New("missing EncodeTime in EncoderConfig")
}
_encoderMutex.RLock()
defer _encoderMutex.RUnlock()
if name == "" {
return nil, errNoEncoderNameSpecified
}
constructor, ok := _encoderNameToConstructor[name]
if !ok {
return nil, fmt.Errorf("no encoder registered for name %q", name)View on GitHub (pinned to bbd4ecbd87)
Solutions
- Use a unique name, e.g. "mycompany-json" instead of "json"
- Guard with zapcore.EncoderNameExistFunc or check registration once via sync.Once
- Remove duplicate init-time registration calls
Example fix
// before
err := zap.RegisterEncoder("json", myCtor) // collides with built-in
// after
err := zap.RegisterEncoder("mycompany-json", myCtor) Defensive patterns
Strategy: try-catch
Validate before calling
if err := zap.RegisterEncoder(name, ctor); err != nil {
if strings.Contains(err.Error(), "already registered") {
return nil // idempotent re-registration is fine
}
return err
} Try / catch
var once sync.Once
func ensureEncoder() error {
var err error
once.Do(func() { err = zap.RegisterEncoder("myencoder", ctor) })
return err
} Prevention
- Register custom encoders under unique, namespaced names
- Use sync.Once or init-only registration to avoid duplicates
- Never re-register built-in names like "json" or "console"
When it happens
Trigger: Calling zap.RegisterEncoder("json", ctor) or the color-level helpers with a name that already exists (including built-ins "json" and "console", or a name registered earlier in the process).
Common situations: Registering encoders in an init() that runs more than once (e.g. across tests or package re-imports in one binary); re-registering a built-in name; multiple libraries registering the same custom encoder name.
Related errors
- no encoder name specified
- no encoder registered for name %q
- missing EncodeTime in EncoderConfig
- can't register a sink factory for empty string
- missing Level
AI-assisted analysis of uber-go/zap@bbd4ecbd87 (2026-08-31).
Data as JSON: /api/errors/c628ab94c89bfce6.
Report an issue: GitHub.