goharbor/harbor · critical

no worker worker is configured

Error message

no worker worker is configured

What it means

Jobservice config load fails with 'no worker worker is configured' (a known duplicated-word typo in the message) when the loaded configuration has no worker_pool section, so PoolConfig is nil. It is raised by config validation at startup and prevents jobservice from starting at all.

Source

Thrown at src/jobservice/config/config.go:333

	if !utils.IsValidPort(c.Port) {
		return fmt.Errorf("port number should be a none zero integer and less or equal 65535, but current is %d", c.Port)
	}

	if c.Protocol == JobServiceProtocolHTTPS {
		if c.HTTPSConfig == nil {
			return fmt.Errorf("certificate must be configured if serve with protocol %s", c.Protocol)
		}

		if utils.IsEmptyStr(c.HTTPSConfig.Cert) ||
			!utils.FileExists(c.HTTPSConfig.Cert) ||
			utils.IsEmptyStr(c.HTTPSConfig.Key) ||
			!utils.FileExists(c.HTTPSConfig.Key) {
			return fmt.Errorf("certificate for protocol %s is not correctly configured", c.Protocol)
		}
	}

	if c.PoolConfig == nil {
		return errors.New("no worker worker is configured")
	}

	if c.PoolConfig.Backend != JobServicePoolBackendRedis {
		return fmt.Errorf("worker worker backend %s does not support", c.PoolConfig.Backend)
	}

	// When backend is redis
	if c.PoolConfig.Backend == JobServicePoolBackendRedis {
		if c.PoolConfig.RedisPoolCfg == nil {
			return fmt.Errorf("redis worker must be configured when backend is set to '%s'", c.PoolConfig.Backend)
		}
		if utils.IsEmptyStr(c.PoolConfig.RedisPoolCfg.RedisURL) {
			return errors.New("URL of redis worker is empty")
		}
		if !strings.Contains(c.PoolConfig.RedisPoolCfg.RedisURL, "://") {
			return errors.New("invalid redis URL")
		}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Add a worker_pool section with backend: redis plus a redis_pool block (the only supported backend)
  2. Validate YAML indentation against the jobservice config template in the repo
  3. Start from the shipped default config and edit it rather than writing from scratch

Example fix

# before
protocol: http
http_config:
  port: 8080

# after
protocol: http
http_config:
  port: 8080
worker_pool:
  backend: redis
  redis_pool:
    redis_url: redis://:password@redis:6379/5
    namespace: harbor_jobservice
    worker_count: 10
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight the config before handing it to jobservice
var cfg Config
_ = yaml.Unmarshal(raw, &cfg)
if cfg.PoolConfig == nil {
    return errors.New("config.yml missing worker_pool section")
}
if cfg.PoolConfig.Backend != "redis" {
    return errors.New("worker_pool.backend must be redis")
}

Type guard

func isNoWorkerConfigured(err error) bool { return err != nil && strings.Contains(err.Error(), "no worker worker is configured") }

Try / catch

if err := cfg.Load(...); err != nil {
    if strings.Contains(err.Error(), "no worker worker is configured") {
        return errors.New("add worker_pool { backend: redis, redis_pool: {...} } to config.yml")
    }
    return err
}

Prevention

When it happens

Trigger: Launching jobservice with a config.yml whose worker_pool block is missing or mis-indented so it never lands under the top-level key (PoolConfig parses as nil).

Common situations: Hand-written minimal configs; template drift after upgrading to a config layout that requires worker_pool; YAML indentation placing worker_pool under another key.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/2dc0a14124b054e4. Report an issue: GitHub.