{"record":{"id":"aa068a0dc2e61ec1","repo":"goharbor/harbor","slug":"missing-logger-config-of-job-service","errorCode":null,"errorMessage":"missing logger config of job service","messagePattern":"missing logger config of job service","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/jobservice/config/config.go","lineNumber":363,"sourceCode":"\t\tif utils.IsEmptyStr(c.PoolConfig.RedisPoolCfg.RedisURL) {\n\t\t\treturn errors.New(\"URL of redis worker is empty\")\n\t\t}\n\t\tif !strings.Contains(c.PoolConfig.RedisPoolCfg.RedisURL, \"://\") {\n\t\t\treturn errors.New(\"invalid redis URL\")\n\t\t}\n\n\t\tif _, err := url.Parse(c.PoolConfig.RedisPoolCfg.RedisURL); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid redis URL: %s\", err.Error())\n\t\t}\n\n\t\tif utils.IsEmptyStr(c.PoolConfig.RedisPoolCfg.Namespace) {\n\t\t\treturn errors.New(\"namespace of redis worker is required\")\n\t\t}\n\t}\n\n\t// Job service loggers\n\tif len(c.LoggerConfigs) == 0 {\n\t\treturn errors.New(\"missing logger config of job service\")\n\t}\n\n\t// Job loggers\n\tif len(c.JobLoggerConfigs) == 0 {\n\t\treturn errors.New(\"missing logger config of job\")\n\t}\n\n\treturn nil // valid\n}\n\n// MaxUpdateDuration the max time for an execution can be updated by task\nfunc MaxUpdateDuration() time.Duration {\n\tif DefaultConfig != nil && DefaultConfig.ReaperConfig != nil && DefaultConfig.ReaperConfig.MaxUpdateHour > 24 {\n\t\treturn time.Duration(DefaultConfig.ReaperConfig.MaxUpdateHour) * time.Hour\n\t}\n\treturn 24 * time.Hour\n}\n","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/jobservice/config/config.go#L345-L381","documentation":"Config.validate() (src/jobservice/config/config.go:363) requires at least one job service logger (c.LoggerConfigs, YAML key 'loggers'). These sinks carry the service's own operational logs; with none configured the service would run blind, so startup aborts with this error.","triggerScenarios":"A jobservice config whose 'loggers' array is empty or entirely missing — e.g. a trimmed-down config.yml where only the pool section was copied — when Load() runs validation.","commonSituations":"Custom minimal configs in bespoke images; Helm values rendering loggers: []; config templates left incomplete after a Harbor upgrade.","solutions":["Restore the stock logger block from Harbor's default jobservice config template (a STD_OUTPUT or FILE sink at level INFO)","If building config programmatically, append at least one *LoggerConfig before calling Load/Validate","Inspect the rendered config.yml inside the container to confirm the loggers list survived templating"],"exampleFix":"# before\nloggers: []\n# after\nloggers:\n  - name: STD_OUTPUT\n    level: INFO\n    sweeper_duration: 1\n    backend: STD_OUTPUT","handlingStrategy":"validation","validationCode":"if len(cfg.LoggerConfigs) == 0 {\n    return errors.New(\"jobservice config must define at least one logger\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start from Harbor's stock jobservice config template and override values, do not rebuild it","Diff the rendered config against the default after template changes","Validate the full config in a pre-deploy smoke test"],"tags":["configuration","logging","jobservice","harbor","startup"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}