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

  1. Use a unique name, e.g. "mycompany-json" instead of "json"
  2. Guard with zapcore.EncoderNameExistFunc or check registration once via sync.Once
  3. 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

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


AI-assisted analysis of uber-go/zap@bbd4ecbd87 (2026-08-31). Data as JSON: /api/errors/c628ab94c89bfce6. Report an issue: GitHub.