{"record":{"id":"fb54ccc2811cf25a","repo":"zylon-ai/private-gpt","slug":"visibility-timeout-should-be-greater-than-hard-tim","errorCode":null,"errorMessage":"Visibility timeout should be greater than hard time limit","messagePattern":"Visibility timeout should be greater than hard time limit","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"private_gpt/settings/settings.py","lineNumber":1186,"sourceCode":"            if self.hard_time_limit and self.soft_time_limit > self.hard_time_limit:\n                raise ValueError(\n                    \"Soft time limit should be less than or equal to hard time limit\"\n                )\n\n            if (\n                self.visibility_timeout\n                and self.visibility_timeout < self.soft_time_limit\n            ):\n                raise ValueError(\n                    \"Visibility timeout should be greater than soft time limit\"\n                )\n\n        if self.hard_time_limit:\n            if (\n                self.visibility_timeout\n                and self.visibility_timeout < self.hard_time_limit\n            ):\n                raise ValueError(\n                    \"Visibility timeout should be greater than hard time limit\"\n                )\n\n        return True\n\n\nclass RedisSettings(BaseModel):\n    host: str = Field(description=\"Redis host\")\n    username: str | None = Field(default=None, description=\"Redis username\")\n    password: str | None = Field(default=None, description=\"Redis password\")\n    database: str | None = Field(default=None, description=\"Redis name\")\n\n    @property\n    def url(self) -> str:\n        \"\"\"Database URL without the protocol.\"\"\"\n        username_path = f\"{self.username}\" if self.username else \"\"\n        password_path = f\"{self.password}\" if self.password else \"\"\n        credentials = (","sourceCodeStart":1168,"sourceCodeEnd":1204,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/settings/settings.py#L1168-L1204","documentation":"Config-validation ValueError from CelerySettings.validate_config: when hard_time_limit and visibility_timeout are both set, visibility_timeout must be >= hard_time_limit. Even a task that runs all the way to its hard kill must stay inside the Redis visibility window, otherwise Redis redelivers it while the first execution is still being killed, causing duplicate side effects.","triggerScenarios":"Redis broker with visibility_timeout: 120 and hard_time_limit: 600; introducing generous hard limits (e.g. for batch jobs) on a config whose visibility_timeout was tuned for quick tasks; visibility_timeout left at a low default from a template.","commonSituations":"Workload mix shifting from short to long tasks; ops adding hard_time_limit for safety without revisiting broker settings; staging/prod env var divergence.","solutions":["Set visibility_timeout above hard_time_limit (rule of thumb: hard limit plus several minutes of headroom).","Or reduce hard_time_limit if such long tasks are a misconfiguration.","Keep the full ordering consistent: visibility_timeout >= hard_time_limit >= soft_time_limit.","Restart the API and all workers so the new window takes effect."],"exampleFix":"# before\ncelery:\n  broker_mode: redis\n  visibility_timeout: 300\n  hard_time_limit: 600\n# after\ncelery:\n  broker_mode: redis\n  visibility_timeout: 900\n  hard_time_limit: 600","handlingStrategy":"validation","validationCode":"hard, vis = cfg['celery'].get('hard_time_limit'), cfg['celery'].get('visibility_timeout')\nif hard and vis:\n    assert vis >= hard, f'visibility_timeout ({vis}) must be >= hard_time_limit ({hard})'","typeGuard":"const visibilityCoversHard = (c: { visibility_timeout?: number; hard_time_limit?: number }): boolean =>\n  c.visibility_timeout == null || c.hard_time_limit == null || c.visibility_timeout >= c.hard_time_limit;","tryCatchPattern":null,"preventionTips":["Enforce ordering vis >= hard >= soft in a shared config-lint rule.","Document the invariant next to the celery settings in your repo.","Fail CI on settings that do not load cleanly."],"tags":["celery","redis","configuration","timeouts","task-queue"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}