zylon-ai/private-gpt · critical · ValueError

Visibility timeout should be set when broker or backend is R

Error message

Visibility timeout should be set when broker or backend is Redis

What it means

Config-validation ValueError from CelerySettings.validate_config: when broker_mode or backend_mode is 'redis', visibility_timeout must be set. With Redis, Celery's early-ack behavior can redeliver a task before it finishes, producing duplicates unless visibility_timeout exceeds the longest task; the validator therefore refuses Redis configs without it.

Source

Thrown at private_gpt/settings/settings.py:1163

                int(data["hard_time_limit"]) if data["hard_time_limit"] else None
            )
        if "max_memory_per_child" in data:
            data["max_memory_per_child"] = (
                int(data["max_memory_per_child"])
                if data["max_memory_per_child"]
                else None
            )
        if "visibility_timeout" in data:
            data["visibility_timeout"] = (
                int(data["visibility_timeout"]) if data["visibility_timeout"] else None
            )
        super().__init__(**data)

    def validate_config(self) -> bool:
        # Check if visibility timeout is set when broker or backend is redis
        if self.broker_mode == "redis" or self.backend_mode == "redis":
            if not self.visibility_timeout:
                raise ValueError(
                    "Visibility timeout should be set when broker or backend is Redis"
                )

        if self.soft_time_limit:
            if self.hard_time_limit and self.soft_time_limit > self.hard_time_limit:
                raise ValueError(
                    "Soft time limit should be less than or equal to hard time limit"
                )

            if (
                self.visibility_timeout
                and self.visibility_timeout < self.soft_time_limit
            ):
                raise ValueError(
                    "Visibility timeout should be greater than soft time limit"
                )

        if self.hard_time_limit:

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Set celery visibility_timeout in settings (seconds), e.g. visibility_timeout: 3600 — comfortably above your longest task.
  2. If it is set but ignored, check the env/YAML value is not empty/0 (the loader maps falsy to None) and the key nesting matches the schema.
  3. If you did not intend Redis, set broker_mode/backend_mode back to the intended non-redis value.
  4. Restart the API and worker processes after fixing the config — validation runs at settings load.

Example fix

# before (settings.yaml)
celery:
  broker_mode: redis
  backend_mode: redis
# after
celery:
  broker_mode: redis
  backend_mode: redis
  visibility_timeout: 7200
Defensive patterns

Strategy: validation

Validate before calling

cfg = load_settings_profile('prod')
celery_cfg = cfg.get('celery', {})
if 'redis' in (celery_cfg.get('broker_mode'), celery_cfg.get('backend_mode')):
    assert int(celery_cfg.get('visibility_timeout') or 0) > 0, 'redis celery needs visibility_timeout'

Type guard

const redisNeedsVisibility = (c: { broker_mode?: string; backend_mode?: string; visibility_timeout?: number }): boolean =>
  (c.broker_mode === 'redis' || c.backend_mode === 'redis') && !c.visibility_timeout;

Prevention

When it happens

Trigger: settings.yaml (or env vars) with celery broker_mode: redis and/or backend_mode: redis but no visibility_timeout (or an explicit null/0 — the loader coerces falsy values to None). Switching the broker from rabbitmq to redis in an existing config that never had the key.

Common situations: Migrating from RabbitMQ to Redis for simpler ops and reusing the old YAML; adding a redis backend for result tracking; visibility_timeout set to 0 or empty string in env vars being coerced to None; copy-pasted minimal example configs.

Understand the failure class

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/a5dc9746653738cd. Report an issue: GitHub.