{"record":{"id":"67cc187de93b323c","repo":"uber-go/zap","slug":"missing-encodetime-in-encoderconfig","errorCode":null,"errorMessage":"missing EncodeTime in EncoderConfig","messagePattern":"missing EncodeTime in EncoderConfig","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"encoder.go","lineNumber":66,"sourceCode":"//\n// Attempting to register an encoder whose name is already taken returns an\n// error.\nfunc RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error {\n\t_encoderMutex.Lock()\n\tdefer _encoderMutex.Unlock()\n\tif name == \"\" {\n\t\treturn errNoEncoderNameSpecified\n\t}\n\tif _, ok := _encoderNameToConstructor[name]; ok {\n\t\treturn fmt.Errorf(\"encoder already registered for name %q\", name)\n\t}\n\t_encoderNameToConstructor[name] = constructor\n\treturn nil\n}\n\nfunc newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {\n\tif encoderConfig.TimeKey != \"\" && encoderConfig.EncodeTime == nil {\n\t\treturn nil, errors.New(\"missing EncodeTime in EncoderConfig\")\n\t}\n\n\t_encoderMutex.RLock()\n\tdefer _encoderMutex.RUnlock()\n\tif name == \"\" {\n\t\treturn nil, errNoEncoderNameSpecified\n\t}\n\tconstructor, ok := _encoderNameToConstructor[name]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no encoder registered for name %q\", name)\n\t}\n\treturn constructor(encoderConfig)\n}\n","sourceCodeStart":48,"sourceCodeEnd":80,"githubUrl":"https://github.com/uber-go/zap/blob/bbd4ecbd8760678fdbac94c93d9aca8069c83b2f/encoder.go#L48-L80","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ncfg := zapcore.EncoderConfig{TimeKey: \"ts\", MessageKey: \"msg\"}\n// after\ncfg := zapcore.EncoderConfig{TimeKey: \"ts\", MessageKey: \"msg\", EncodeTime: zapcore.ISO8601TimeEncoder}","handlingStrategy":"validation","validationCode":"if cfg.TimeKey != \"\" && cfg.EncodeTime == nil {\n    cfg.EncodeTime = zapcore.ISO8601TimeEncoder\n}\nenc := zapcore.NewJSONEncoder(cfg)","typeGuard":"func hasEncodeTime(c zapcore.EncoderConfig) bool {\n    return c.TimeKey == \"\" || c.EncodeTime != nil\n}","tryCatchPattern":null,"preventionTips":["Always set EncodeTime when setting TimeKey","Use zap.NewProductionEncoderConfig() as a base, which presets EncodeTime","If disabling timestamps, clear TimeKey rather than EncodeTime"],"tags":["encoder","config","zap","go"],"backgroundTag":"missing-required-config-field","analyzedSha":"bbd4ecbd8760678fdbac94c93d9aca8069c83b2f","analyzedAt":"2026-08-31T13:01:40.228Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}