{"record":{"id":"d61158087f335639","repo":"apache/superset","slug":"import-failed-for-an-unknown-reason","errorCode":null,"errorMessage":"Import failed for an unknown reason","messagePattern":"Import failed for an unknown reason","errorType":"exception","errorClass":"ImportFailedError","httpStatus":500,"severity":"error","filePath":"superset/commands/database/importers/v1/utils.py","lineNumber":63,"sourceCode":"    can_write = ignore_permissions or security_manager.can_access(\n        \"can_write\",\n        \"Database\",\n    )\n    existing = db.session.query(Database).filter_by(uuid=config[\"uuid\"]).first()\n    if existing:\n        if not overwrite or not can_write:\n            return existing\n        config[\"id\"] = existing.id\n    elif not can_write:\n        raise ImportFailedError(\n            \"Database doesn't exist and user doesn't have permission to create databases\"  # noqa: E501\n        )\n    # Check if this URI is allowed (skip for system imports like examples)\n    if app.config[\"PREVENT_UNSAFE_DB_CONNECTIONS\"] and not ignore_permissions:\n        try:\n            check_sqlalchemy_uri(make_url_safe(config[\"sqlalchemy_uri\"]))\n        except SupersetSecurityException as exc:\n            raise ImportFailedError(exc.message) from exc\n    # https://github.com/apache/superset/pull/16756 renamed ``csv`` to ``file``.\n    # Handle both old and new field names, defaulting to True for examples database\n    if \"allow_csv_upload\" in config:\n        config[\"allow_file_upload\"] = config.pop(\"allow_csv_upload\")\n    elif \"allow_file_upload\" not in config:\n        # Default to True for backward compatibility\n        config[\"allow_file_upload\"] = True\n\n    if \"schemas_allowed_for_csv_upload\" in config.get(\"extra\", {}):\n        config[\"extra\"][\"schemas_allowed_for_file_upload\"] = config[\"extra\"].pop(\n            \"schemas_allowed_for_csv_upload\"\n        )\n\n    # TODO (betodealmeida): move this logic to import_from_dict\n    config[\"extra\"] = json.dumps(config[\"extra\"])\n\n    # Convert masked_encrypted_extra → encrypted_extra before importing.\n    # For existing DBs, reveal masked sensitive values from current encrypted_extra.","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/database/importers/v1/utils.py#L45-L81","documentation":"ImportFailedError raised from the PREVENT_UNSAFE_DB_CONNECTIONS check in importers/v1/utils.py: before creating/updating the imported database, make_url_safe(config['sqlalchemy_uri']) is passed to check_sqlalchemy_uri(); a SupersetSecurityException (blocked scheme/host) is re-raised as ImportFailedError(exc.message). When the security exception carries no message the ImportFailedError default text ('Import failed for an unknown reason') surfaces — the underlying cause is the URI being rejected as unsafe.","triggerScenarios":"POST /api/v1/database/import/ with PREVENT_UNSAFE_DB_CONNECTIONS=True (non-default) and a bundle whose sqlalchemy_uri uses a disallowed scheme (e.g. sqlite) or points at a host the check forbids (e.g. loopback/reserved ranges blocked by policy).","commonSituations":"Security-hardened deployments that enable PREVENT_UNSAFE_DB_CONNECTIONS; importing example/demo bundles that embed sqlite:// URIs; bundles authored on laptops with localhost databases.","solutions":["Identify the blocked URI: unzip the bundle and read the database YAML's sqlalchemy_uri.","Change the bundle to a permitted engine/host, or import the database separately with an approved URI and let the bundle resolve it by UUID.","If the destination is genuinely safe, have the operator adjust the policy (PREVENT_UNSAFE_DB_CONNECTIONS / allowed-hosts configuration) rather than bypassing it per-request — the check is skipped only for system imports (ignore_permissions)."],"exampleFix":"# before: bundle contains\n# sqlalchemy_uri: sqlite:///examples.db\n# PREVENT_UNSAFE_DB_CONNECTIONS=True -> ImportFailedError\n\n# after: point the bundle at an approved server\n# sqlalchemy_uri: postgresql://user:pass@dw.internal:5432/examples","handlingStrategy":"validation","validationCode":"from superset.utils.core import check_sqlalchemy_uri\nfrom sqlalchemy.engine import make_url\nfrom superset.exceptions import SupersetSecurityException\n\ndef uri_is_import_safe(uri: str) -> bool:\n    try:\n        check_sqlalchemy_uri(make_url(uri))\n        return True\n    except SupersetSecurityException:\n        return False","typeGuard":null,"tryCatchPattern":"from superset.commands.importers.exceptions import ImportFailedError\n\ntry:\n    dispatcher.run()\nexcept ImportFailedError:\n    # when PREVENT_UNSAFE_DB_CONNECTIONS is on, inspect the bundle's URI and\n    # either fix the bundle or have the operator adjust policy\n    ...","preventionTips":["Keep imported sqlalchemy_uri values on approved engines/hosts when PREVENT_UNSAFE_DB_CONNECTIONS is enabled.","Strip demo sqlite URIs from bundles before importing into hardened environments.","Prefer resolving an already-approved database by UUID over creating new ones via import."],"tags":["import-export","security","ssrf","sqlalchemy-uri","config"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}