goharbor/harbor · critical

invalid redis URL

Error message

invalid redis URL

What it means

Harbor job service configuration error thrown from Config.validate() (src/jobservice/config/config.go:349) when the worker pool backend is 'redis' but RedisPoolCfg.RedisURL contains no '://' scheme separator. The service refuses to start because the Redis pool needs a full URL to dial. Note that the normal YAML/env load path auto-prepends 'redis://' to scheme-less addresses (config.go:172-183), so this variant mainly fires when a Config struct is built programmatically and validated directly, or when the later url.Parse fails (that sibling case reports 'invalid redis URL: %s').

Source

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

	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")
		}

		if _, err := url.Parse(c.PoolConfig.RedisPoolCfg.RedisURL); err != nil {
			return fmt.Errorf("invalid redis URL: %s", err.Error())
		}

		if utils.IsEmptyStr(c.PoolConfig.RedisPoolCfg.Namespace) {
			return errors.New("namespace of redis worker is required")
		}
	}

	// Job service loggers
	if len(c.LoggerConfigs) == 0 {
		return errors.New("missing logger config of job service")
	}

	// Job loggers
	if len(c.JobLoggerConfigs) == 0 {

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Write the URL with an explicit scheme: redis://:password@host:6379/0 (rediss:// for TLS)
  2. Prefer loading config through config.Load from YAML/env — it prepends redis:// to scheme-less addresses before validating
  3. Check the effective value of JOB_SERVICE_POOL_REDIS_URL / jobservice.pool.redis_url inside the jobservice container
  4. If Redis was not intended, set the pool backend to 'database' and drop the Redis pool config

Example fix

// before
cfg.PoolConfig.RedisPoolCfg.RedisURL = "redis:6379"
// after
cfg.PoolConfig.RedisPoolCfg.RedisURL = "redis://:password@redis:6379/0"
Defensive patterns

Strategy: validation

Validate before calling

func checkRedisURL(raw string) error {
    if !strings.Contains(raw, "://") {
        return fmt.Errorf("redis URL %q must include a scheme (redis:// or rediss://)", raw)
    }
    if _, err := url.Parse(raw); err != nil {
        return fmt.Errorf("redis URL does not parse: %w", err)
    }
    return nil
}

Type guard

func isSchemedRedisURL(raw string) bool {
    return strings.Contains(raw, "://")
}

Prevention

When it happens

Trigger: Calling Load/Validate on a Config with PoolConfig.Backend == JobServicePoolBackendRedis and RedisPoolCfg.RedisURL like 'redis:6379' or 'myredis:6379' (no scheme); constructing the config by hand in tests or embedded jobservice use instead of going through the YAML loader; env JOB_SERVICE_POOL_REDIS_URL set to a scheme-less host:port in a code path that skips the translate step.

Common situations: Older docs/examples showing host:port form; Helm values injecting a scheme-less URL into a custom image; unit tests constructing Config directly; copy-paste of 'redis:6379' from docker-compose service names.

Related errors


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