uber-go/zap · error
missing EncodeTime in EncoderConfig
Error message
missing EncodeTime in EncoderConfig
What it means
newEncoder (used by zap.New production helpers and Config.buildEncoder) rejects an EncoderConfig whose TimeKey is set but whose EncodeTime function is nil, since zap cannot format timestamps without an EncodeTime. The check only applies when TimeKey is non-empty (i.e. time entries are emitted).
Source
Thrown at encoder.go:66
//
// 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)
}
return constructor(encoderConfig)
}
View on GitHub (pinned to bbd4ecbd87)
Solutions
- Set EncodeTime in the EncoderConfig, e.g. zapcore.EpochTimeEncoder, ISO8601TimeEncoder, or RFC3339TimeEncoder
- If you don't want timestamps, clear TimeKey to "" so the check is skipped
Example fix
// before
cfg := zapcore.EncoderConfig{TimeKey: "ts", MessageKey: "msg"}
// after
cfg := zapcore.EncoderConfig{TimeKey: "ts", MessageKey: "msg", EncodeTime: zapcore.ISO8601TimeEncoder} Defensive patterns
Strategy: validation
Validate before calling
if cfg.TimeKey != "" && cfg.EncodeTime == nil {
cfg.EncodeTime = zapcore.ISO8601TimeEncoder
}
enc := zapcore.NewJSONEncoder(cfg) Type guard
func hasEncodeTime(c zapcore.EncoderConfig) bool {
return c.TimeKey == "" || c.EncodeTime != nil
} Prevention
- Always set EncodeTime when setting TimeKey
- Use zap.NewProductionEncoderConfig() as a base, which presets EncodeTime
- If disabling timestamps, clear TimeKey rather than EncodeTime
When it happens
Trigger: Constructing a zapcore.EncoderConfig manually with TimeKey set (e.g. "ts") but leaving EncodeTime nil, then calling zap.New(...) with that config or an encoder built from it.
Common situations: Copying an EncoderConfig snippet from docs but omitting EncodeTime; building encoder configs from structured/JSON config files where function fields cannot be deserialized and default to nil.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- no encoder registered for name %q
- missing Level
- no encoder name specified
- encoder already registered for name %q
- must specify logging level
AI-assisted analysis of uber-go/zap@bbd4ecbd87 (2026-08-31).
Data as JSON: /api/errors/67cc187de93b323c.
Report an issue: GitHub.