apache/superset · error · ImportFailedError
User doesn't have permission to create or update databases
Error message
User doesn't have permission to create or update databases
What it means
ImportFailedError ("User doesn't have permission to create or update databases") is raised by the legacy v0 dataset importer when the import bundle contains a `databases` section, a request user is present, and that user lacks the `can_write` permission on Database. The v0 path creates/updates the embedded database connections, so it mirrors the v1 import commands' requirement for database write access. When no user is present (CLI imports), the check is skipped.
Source
Thrown at superset/commands/dataset/importers/v0.py:227
def import_from_dict(data: dict[str, Any], sync: Optional[list[str]] = None) -> None:
"""Imports databases from dictionary"""
if not sync:
sync = []
if isinstance(data, dict):
databases = data.get(DATABASES_KEY, [])
# This legacy path creates/updates the embedded database connections.
# Mirror the versioned (v1) import commands and require database write
# permission for the objects being created here. Only enforced when there
# is something to import and a request user is present, so the CLI import
# paths keep working.
if (
databases
and get_user()
and not security_manager.can_access("can_write", "Database")
):
raise ImportFailedError(
"User doesn't have permission to create or update databases"
)
logger.info("Importing %d %s", len(databases), DATABASES_KEY)
for database in databases:
db_obj = Database.import_from_dict(database, sync=sync)
# ``import_from_dict`` sets fields via setattr, bypassing
# ``set_sqlalchemy_uri``. Call it explicitly so that any plaintext
# password in the URI is extracted into the encrypted ``password``
# column and replaced with the password mask in ``sqlalchemy_uri``.
if db_obj is not None:
# Only call set_sqlalchemy_uri when the imported URI carries a real
# password (non-empty and not the password mask). If the URI has no
# password segment — common when users keep secrets out of YAML and
# rely on the encrypted ``password`` column from a prior run —
# calling set_sqlalchemy_uri would set ``password = None`` and break
# existing connections.
parsed = make_url_safe(db_obj.sqlalchemy_uri)
if parsed.password and parsed.password != PASSWORD_MASK:View on GitHub (pinned to f4587218dd)
Solutions
- Grant the importing user `can_write` on Database (or perform the import as Admin).
- Strip the `databases` section from the bundle so only datasets are imported — the databases must then already exist on the target.
- For automated flows, use the CLI import path, which runs without a request user and is not subject to this check.
Defensive patterns
Strategy: validation
Validate before calling
# Before a UI upload, check permission when the bundle carries databases
import yaml
from superset import security_manager
from flask_login import current_user
def v0_import_allowed(contents: dict) -> bool:
carries_databases = any(
isinstance(yaml.safe_load(c), dict) and "databases" in yaml.safe_load(c)
for c in contents.values()
)
if not carries_databases:
return True
return security_manager.can_access("can_write", "Database") Try / catch
from superset.commands.exceptions import ImportFailedError
try:
ImportDatasetsCommand(contents, {})
except ImportFailedError as ex:
if "permission to create or update databases" in str(ex):
# either drop the databases section or escalate to an admin — retry unchanged is futile
strip_databases_and_retry(contents) or escalate_to_admin() Prevention
- Import as Admin, or pre-grant can_write on Database to the importing role.
- Prefer v1 (versioned) bundles with database references by name instead of embedded definitions.
- For automation, use the CLI import path which runs without a request user.
When it happens
Trigger: Uploading a legacy UI export (v0 format with DATABASES_KEY) to the dataset import endpoint as a non-admin without can_write on Database; a Gamma/Alpha user importing bundles that carry their own database definitions.
Common situations: Sharing legacy export files across teams; importing bundles produced by the old UI export into a deployment with stricter RBAC; service accounts without database-write grants used for imports.
Related errors
- Changing this dataset is forbidden.
- Changing this dataset is forbidden
- You don't have access to this dataset.
- Database doesn't exist and user doesn't have permission to c
- Dataset parameters are invalid.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/4547093101e31e9c.
Report an issue: GitHub.