apache/superset · error · ImportFailedError

User doesn't have permission to create or update datasets

Error message

User doesn't have permission to create or update datasets

What it means

ImportFailedError('User doesn't have permission to create or update datasets') is raised by the legacy v0 import_dashboards() when the payload contains datasources and the current user lacks the 'can_write' permission on the Dataset resource. The v0 format embeds dataset definitions, so importing it creates/updates datasets, which requires dataset write permission. The check is skipped only when no user is present (CLI/background paths).

Source

Thrown at superset/commands/dashboard/importers/v0.py:319

    import_time: Optional[int] = None,
) -> None:
    """Imports dashboards from a stream to databases"""
    current_tt = int(time.time())
    import_time = current_tt if import_time is None else import_time
    data = json.loads(content, object_hook=decode_dashboards)
    if not data:
        raise DashboardImportException(_("No data in file"))
    dataset_id_mapping: dict[int, int] = {}
    # This legacy path creates/updates the embedded datasets. Mirror the
    # versioned (v1) import commands and require dataset 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 (
        data["datasources"]
        and get_user()
        and not security_manager.can_access("can_write", "Dataset")
    ):
        raise ImportFailedError(
            "User doesn't have permission to create or update datasets"
        )
    for table in data["datasources"]:
        new_dataset_id = import_dataset(table, database_id, import_time=import_time)
        params = json.loads(table.params)
        dataset_id_mapping[params["remote_id"]] = new_dataset_id

    for dashboard in data["dashboards"]:
        import_dashboard(dashboard, dataset_id_mapping, import_time=import_time)


class ImportDashboardsCommand(BaseCommand):
    """
    Import dashboard in JSON format.

    This is the original unversioned format used to export and import dashboards
    in Superset.
    """

View on GitHub (pinned to f4587218dd)

Solutions

  1. Grant the importing user's role 'can_write' on Dataset (Security -> Roles -> Edit, Permission: can_write on datasets view), since v0 bundles cannot import without it.
  2. Migrate the workflow to the v1 ZIP export format, which separates dataset and dashboard permissions via import permissions on each resource.
  3. Or strip embedded datasources and pre-create the datasets, so the payload's 'datasources' is empty and the check passes.

Example fix

# before
# role lacks can_write on Dataset; payload has datasources
import_dashboards(content)  # ImportFailedError

# after (pre-create datasets, import dashboard-only payload)
data = json.loads(content)
data['datasources'] = []  # datasets already exist via UI/API
import_dashboards(json.dumps(data))
Defensive patterns

Strategy: validation

Validate before calling

from flask import g
import json

data = json.loads(content)
from superset.extensions import security_manager
if data.get('datasources') and not security_manager.can_access('can_write', 'Dataset'):
    # pre-create datasets and strip them, or escalate permission
    raise PermissionError('v0 import needs Dataset can_write when datasources embedded')

Try / catch

try:
    import_dashboards(content)
except ImportFailedError as ex:
    if 'permission to create or update datasets' in str(ex):
        strip_datasources_and_retry_or_grant_permission()

Prevention

When it happens

Trigger: Running a v0 JSON dashboard import over HTTP as a user whose role lacks can_write on Dataset, while the file's 'datasources' array is non-empty.

Common situations: Analysts with dashboard-only import rights trying to import legacy bundles that carry their own datasets; role hardening that removed dataset write from a curator role, breaking a previously working import pipeline.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/004586a0facbf1af. Report an issue: GitHub.