{"record":{"id":"ad02578b6074ae24","repo":"ruvnet/RuView","slug":"database-url-must-be-configured-for-non-developmen","errorCode":null,"errorMessage":"Database URL must be configured for non-development environments","messagePattern":"Database URL must be configured for non-development environments","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"archive/v1/src/config/settings.py","lineNumber":290,"sourceCode":"    def get_database_url(self) -> str:\n        \"\"\"Get database URL with fallback.\"\"\"\n        if self.database_url:\n            return self.database_url\n        \n        # Build URL from individual components if available\n        if self.db_host and self.db_name and self.db_user:\n            password_part = f\":{self.db_password}\" if self.db_password else \"\"\n            return f\"postgresql://{self.db_user}{password_part}@{self.db_host}:{self.db_port}/{self.db_name}\"\n        \n        # Default SQLite database for development\n        if self.is_development:\n            return f\"sqlite:///{self.data_storage_path}/wifi_densepose.db\"\n        \n        # SQLite failsafe for production if enabled\n        if self.enable_database_failsafe:\n            return f\"sqlite:///{self.sqlite_fallback_path}\"\n        \n        raise ValueError(\"Database URL must be configured for non-development environments\")\n    \n    def get_sqlite_fallback_url(self) -> str:\n        \"\"\"Get SQLite fallback database URL.\"\"\"\n        return f\"sqlite:///{self.sqlite_fallback_path}\"\n    \n    def get_redis_url(self) -> Optional[str]:\n        \"\"\"Get Redis URL with fallback.\"\"\"\n        if not self.redis_enabled:\n            return None\n            \n        if self.redis_url:\n            return self.redis_url\n        \n        # Build URL from individual components\n        password_part = f\":{self.redis_password}@\" if self.redis_password else \"\"\n        return f\"redis://{password_part}{self.redis_host}:{self.redis_port}/{self.redis_db}\"\n    \n    def get_cors_config(self) -> Dict[str, Any]:","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/config/settings.py#L272-L308","documentation":"Raised by Settings.get_database_url() in archive/v1/src/config/settings.py when no usable database configuration exists. The method first checks database_url, then the db_host+db_name+db_user triple, then a SQLite default for development, then the SQLite failsafe (enable_database_failsafe, default true). The ValueError fires only when all four paths fail, i.e. a non-development environment with no PostgreSQL coordinates and the failsafe deliberately disabled.","triggerScenarios":"Calling settings.get_database_url() with: environment set to production/testing, database_url unset, at least one of db_host/db_name/db_user missing, and ENABLE_DATABASE_FAILSAFE=false. Also triggered in tests that disable the failsafe to assert DB configuration is present.","commonSituations":"Promoting an app to production without provisioning DATABASE_URL; setting DB_USER but forgetting DB_NAME (the triple requires all three); security hardening that sets enable_database_failsafe=false per policy; staging environments that set ENVIRONMENT=production without a DB service; helm charts that gate DATABASE_URL behind an unset secret.","solutions":["Set DATABASE_URL (e.g. postgresql://user:pass@host:5432/dbname) for the non-development environment — this is the intended production path.","Alternatively provide the full component triple: DB_HOST, DB_NAME, and DB_USER (with DB_PASSWORD as needed); all three must be present.","If a local file DB is acceptable, leave enable_database_failsafe=true (the default) so SQLite at sqlite_fallback_path is used instead of raising.","For real production, treat the failsafe as a hazard (silent data in SQLite) and instead make startup fail: keep the error, fix the env, and add a startup preflight check that verifies database_url exists when environment != development."],"exampleFix":"# before\nENVIRONMENT=production\n# DATABASE_URL unset, DB_HOST/DB_NAME/DB_USER incomplete\nENABLE_DATABASE_FAILSAFE=false\nurl = settings.get_database_url()  # ValueError\n\n# after\nENVIRONMENT=production\nDATABASE_URL=postgresql://wifi:secret@db.internal:5432/wifi_densepose\nurl = settings.get_database_url()","handlingStrategy":"try-catch","validationCode":"required_db = settings.database_url or (\n    settings.db_host and settings.db_name and settings.db_user\n)\nif settings.environment != 'development' and not required_db:\n    raise SystemExit(\n        'DATABASE_URL (or DB_HOST+DB_NAME+DB_USER) is required for '\n        f'environment={settings.environment}'\n    )","typeGuard":null,"tryCatchPattern":"try:\n    url = settings.get_database_url()\nexcept ValueError as e:\n    if 'non-development' in str(e):\n        log.error('No database configured for %s; refusing to fall back to SQLite',\n                  settings.environment)\n        raise\n    raise","preventionTips":["Make DATABASE_URL a required secret in every non-dev deploy manifest (k8s secret, compose env).","Add a startup preflight that fails the container before serving traffic when environment != development and no DB coordinates exist.","Treat enable_database_failsafe=true in production as a silent-data-in-SQLite risk; disable it deliberately after wiring DATABASE_URL."],"tags":["config","database","startup","production","postgresql","sqlite"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}