{"record":{"id":"004586a0facbf1af","repo":"apache/superset","slug":"user-doesn-t-have-permission-to-create-or-update-d","errorCode":null,"errorMessage":"User doesn't have permission to create or update datasets","messagePattern":"User doesn't have permission to create or update datasets","errorType":"exception","errorClass":"ImportFailedError","httpStatus":500,"severity":"error","filePath":"superset/commands/dashboard/importers/v0.py","lineNumber":319,"sourceCode":"    import_time: Optional[int] = None,\n) -> None:\n    \"\"\"Imports dashboards from a stream to databases\"\"\"\n    current_tt = int(time.time())\n    import_time = current_tt if import_time is None else import_time\n    data = json.loads(content, object_hook=decode_dashboards)\n    if not data:\n        raise DashboardImportException(_(\"No data in file\"))\n    dataset_id_mapping: dict[int, int] = {}\n    # This legacy path creates/updates the embedded datasets. Mirror the\n    # versioned (v1) import commands and require dataset write permission for the\n    # objects being created here. Only enforced when there is something to import\n    # and a request user is present, so the CLI import paths keep working.\n    if (\n        data[\"datasources\"]\n        and get_user()\n        and not security_manager.can_access(\"can_write\", \"Dataset\")\n    ):\n        raise ImportFailedError(\n            \"User doesn't have permission to create or update datasets\"\n        )\n    for table in data[\"datasources\"]:\n        new_dataset_id = import_dataset(table, database_id, import_time=import_time)\n        params = json.loads(table.params)\n        dataset_id_mapping[params[\"remote_id\"]] = new_dataset_id\n\n    for dashboard in data[\"dashboards\"]:\n        import_dashboard(dashboard, dataset_id_mapping, import_time=import_time)\n\n\nclass ImportDashboardsCommand(BaseCommand):\n    \"\"\"\n    Import dashboard in JSON format.\n\n    This is the original unversioned format used to export and import dashboards\n    in Superset.\n    \"\"\"","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dashboard/importers/v0.py#L301-L337","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Migrate the workflow to the v1 ZIP export format, which separates dataset and dashboard permissions via import permissions on each resource.","Or strip embedded datasources and pre-create the datasets, so the payload's 'datasources' is empty and the check passes."],"exampleFix":"# before\n# role lacks can_write on Dataset; payload has datasources\nimport_dashboards(content)  # ImportFailedError\n\n# after (pre-create datasets, import dashboard-only payload)\ndata = json.loads(content)\ndata['datasources'] = []  # datasets already exist via UI/API\nimport_dashboards(json.dumps(data))","handlingStrategy":"validation","validationCode":"from flask import g\nimport json\n\ndata = json.loads(content)\nfrom superset.extensions import security_manager\nif data.get('datasources') and not security_manager.can_access('can_write', 'Dataset'):\n    # pre-create datasets and strip them, or escalate permission\n    raise PermissionError('v0 import needs Dataset can_write when datasources embedded')","typeGuard":null,"tryCatchPattern":"try:\n    import_dashboards(content)\nexcept ImportFailedError as ex:\n    if 'permission to create or update datasets' in str(ex):\n        strip_datasources_and_retry_or_grant_permission()","preventionTips":["Grant Dataset can_write to roles that run legacy v0 imports.","Migrate pipelines to the v1 ZIP format with per-resource import permissions.","Pre-create datasets so bundles can ship without embedded datasources."],"tags":["security","rbac","import","dataset","permissions","legacy"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}