langgenius/dify · error · ValueError

PUBSUB_REDIS_URL must be set when default Redis URL cannot b

Error message

PUBSUB_REDIS_URL must be set when default Redis URL cannot be constructed

What it means

Raised by RedisPubSubConfig._build_default_pubsub_url when neither PUBSUB_REDIS_URL (alias EVENT_BUS_REDIS_URL) is set nor the base REDIS_HOST/REDIS_PORT are available to synthesize a URL. The pubsub transport needs a concrete Redis endpoint to connect.

Source

Thrown at api/configs/middleware/cache/redis_pubsub_config.py:76

            "the risk of data loss from Redis auto-eviction under memory pressure.\n"
            "Also accepts ENV: EVENT_BUS_REDIS_CHANNEL_TYPE."
        ),
        default="pubsub",
    )

    PUBSUB_STREAMS_RETENTION_SECONDS: int = Field(
        validation_alias=AliasChoices("EVENT_BUS_STREAMS_RETENTION_SECONDS", "PUBSUB_STREAMS_RETENTION_SECONDS"),
        description=(
            "When using 'streams', expire each stream key this many seconds after the last event is published. "
            "Also accepts ENV: EVENT_BUS_STREAMS_RETENTION_SECONDS."
        ),
        default=600,
    )

    def _build_default_pubsub_url(self) -> str:
        defaults = _redis_defaults(self)
        if not defaults.REDIS_HOST or not defaults.REDIS_PORT:
            raise ValueError("PUBSUB_REDIS_URL must be set when default Redis URL cannot be constructed")

        scheme = "rediss" if defaults.REDIS_USE_SSL else "redis"
        username = defaults.REDIS_USERNAME or None
        password = defaults.REDIS_PASSWORD or None

        userinfo = ""
        if username:
            userinfo = quote_plus(username)
        if password:
            password_part = quote_plus(password)
            userinfo = f"{userinfo}:{password_part}" if userinfo else f":{password_part}"
        if userinfo:
            userinfo = f"{userinfo}@"

        db = defaults.REDIS_DB

        netloc = f"{userinfo}{defaults.REDIS_HOST}:{defaults.REDIS_PORT}"
        return urlunparse((scheme, netloc, f"/{db}", "", "", ""))

View on GitHub (pinned to ef8544b173)

Solutions

  1. Set PUBSUB_REDIS_URL (or EVENT_BUS_REDIS_URL) to a full redis:// URL.
  2. Or ensure REDIS_HOST and REDIS_PORT are both set so the default URL can be built.
  3. If using Redis Cluster/Sentinel, provide PUBSUB_REDIS_URL explicitly since host/port synthesis won't match.

Example fix

// before
REDIS_HOST=
PUBSUB_REDIS_URL=
// after
PUBSUB_REDIS_URL=redis://:password@redis:6379/0
// or
REDIS_HOST=redis
REDIS_PORT=6379
Defensive patterns

Strategy: validation

Validate before calling

def pubsub_resolvable(pubsub_url: str | None, redis_host: str | None, redis_port: int | None) -> bool:
    return bool(pubsub_url and pubsub_url.strip()) or bool(redis_host and redis_port)

Prevention

When it happens

Trigger: Accessing normalized_pubsub_redis_url while PUBSUB_REDIS_URL is unset and REDIS_HOST or REDIS_PORT is empty/falsy (e.g. partial Redis config).

Common situations: Running the event bus without setting REDIS_* or EVENT_BUS_REDIS_URL, or pointing at a separate Redis for pubsub but misspelling the var.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/607b75549428b099. Report an issue: GitHub.