{"record":{"id":"45f5f60bffdf9800","repo":"apache/superset","slug":"database-is-offline","errorCode":null,"errorMessage":"Database is offline.","messagePattern":"Database is offline\\.","errorType":"exception","errorClass":"DatabaseOfflineError","httpStatus":422,"severity":"error","filePath":"superset/commands/database/validate.py","lineNumber":164,"sourceCode":"                    and database.db_engine_spec.needs_oauth2(ex)\n                ):\n                    return\n\n                url = make_url_safe(sqlalchemy_uri)\n                context = {\n                    \"hostname\": url.host,\n                    \"password\": url.password,\n                    \"port\": url.port,\n                    \"username\": url.username,\n                    \"database\": url.database,\n                }\n                errors = database.db_engine_spec.extract_errors(\n                    ex, context, database_name=database.unique_name\n                )\n                raise DatabaseTestConnectionFailedError(errors, status=400) from ex\n\n        if not alive:\n            raise DatabaseOfflineError(\n                SupersetError(\n                    message=__(\"Database is offline.\"),\n                    error_type=SupersetErrorType.GENERIC_DB_ENGINE_ERROR,\n                    level=ErrorLevel.ERROR,\n                ),\n            )\n\n    def _load_model(self) -> None:\n        \"\"\"Load the existing database model if updating.\"\"\"\n        if (database_id := self._properties.get(\"id\")) is not None:\n            self._model = DatabaseDAO.find_by_id(database_id)\n\n    def _get_database_name_error(self) -> Optional[SupersetError]:\n        \"\"\"Check for duplicate database name and return error if found.\"\"\"\n        database_id = self._properties.get(\"id\")\n\n        if database_name := self._properties.get(\"database_name\"):\n            is_unique = (","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/database/validate.py#L146-L182","documentation":"DatabaseOfflineError (HTTP 422) is raised by the database connection-test/validate command when the engine spec's connectivity check completes without raising but reports the database as not alive (`if not alive:` in superset/commands/database/validate.py). It means Superset reached its own validation logic, built a URL, and the resulting connection was determined to be down. It is distinct from DatabaseTestConnectionFailedError, which is raised earlier when the connection attempt itself throws an exception.","triggerScenarios":"Calling the database test-connection endpoint (POST to the database REST API with 'Test Connection' / the validate command) against a database whose server is stopped, unreachable on the network, or whose `db_engine_spec.test_connection` returns alive=False. Also triggered when a saved database entry references a host/port that has since been decommissioned.","commonSituations":"DB server restarted or down for maintenance; firewall/VPC rules blocking the port between Superset and the database; wrong host/port in the SQLAlchemy URI; the database engine was paused (e.g., serverless warehouse suspended); DNS name no longer resolves. This appears frequently in CI where no real database is available.","solutions":["Verify the database server is running and reachable from the Superset host (e.g., `nc -vz <host> <port>` or `psql`/client CLI from the same container).","Re-check the connection parameters in the database settings (hostname, port, username, password, database name) and use the 'Test Connection' button after fixing.","If a network policy or Docker network isolation blocks egress, open the route from the Superset container/pod to the database host and port.","If the engine is a paused/suspended warehouse (Snowflake serverless, BigQuery reservations, etc.), wake it up or adjust keep-alive settings, then retest."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Pre-flight reachability check before saving/testing a Database\nfrom superset.commands.database.validate import DatabaseConnectionCommand\n\ndef database_reachable(db_connection_params: dict) -> bool:\n    import socket\n    host, port = db_connection_params[\"host\"], db_connection_params.get(\"port\")\n    if not host or port is None:\n        return False\n    with socket.socket(socket.AF_INET) as s:\n        s.settimeout(3)\n        return s.connect_ex((host, int(port))) == 0","typeGuard":null,"tryCatchPattern":"from superset.commands.database.exceptions import (\n    DatabaseOfflineError, DatabaseTestConnectionFailedError,\n)\ntry:\n    DatabaseConnectionCommand(...).run()\nexcept DatabaseOfflineError:\n    # 422: engine reported not-alive -> surface 'server down/unreachable', do not retry immediately\n    show_operator_message(\"Database server is offline or unreachable\")\nexcept DatabaseTestConnectionFailedError as ex:\n    # carries extracted engine errors with status 400\n    show_engine_errors(ex.errors[0].message if ex.errors else str(ex))","preventionTips":["Run a TCP/CLI reachability probe from the Superset host before configuring a database connection.","Automate a periodic 'test connection' health job per database so outages surface before user-facing validate calls.","Keep host/port/credentials in one source of truth to avoid drift between config and reality."],"tags":["database","connectivity","connection-test","flask-api"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}