{"record":{"id":"ac306e798b33fa49","repo":"apache/superset","slug":"folder-cannot-have-name-name","errorCode":null,"errorMessage":"Folder cannot have name '{name}'","messagePattern":"Folder cannot have name '(.+?)'","errorType":"validation","errorClass":"ValidationError","httpStatus":422,"severity":"error","filePath":"superset/commands/dataset/update.py","lineNumber":470,"sourceCode":"            raise ValidationError(f\"Cycle detected: {uuid} appears in its ancestry\")\n\n        if uuid in seen_uuids:\n            raise ValidationError(f\"Duplicate UUID in folder structure: {uuid}\")\n        seen_uuids.add(uuid)\n\n        # folders can have duplicate name as long as they're not siblings\n        if name:\n            fqn = tuple(path + [name])\n            if name and fqn in seen_fqns:\n                raise ValidationError(f\"Duplicate folder name: {name}\")\n            seen_fqns.add(fqn)\n\n            # Allow default folders (by UUID) to use reserved names\n            if (\n                name.lower() in {\"metrics\", \"columns\"}\n                and str(uuid) not in DEFAULT_FOLDER_UUIDS\n            ):\n                raise ValidationError(f\"Folder cannot have name '{name}'\")\n\n        # check if metric/column UUID exists (skip default folders)\n        elif (\n            not name\n            and uuid not in valid_uuids\n            and str(uuid) not in DEFAULT_FOLDER_UUIDS\n        ):\n            raise ValidationError(f\"Invalid UUID: {uuid}\")\n\n        # traverse children\n        if children := obj.get(\"children\"):\n            path.append(uuid)\n            queue.extend((folder, path) for folder in children)\n","sourceCodeStart":452,"sourceCodeEnd":484,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dataset/update.py#L452-L484","documentation":"Raised by validate_folders() when a named (user-created) folder uses the reserved names 'metrics' or 'columns' in any casing. Only default folders — identified by the fixed uuids in DEFAULT_FOLDER_UUIDS — may carry those names, because they anchor the built-in pseudo-folders for metrics and columns.","triggerScenarios":"PUT /api/v1/dataset/{id} with a folders entry having name 'Metrics' or 'COLUMNS' (case-insensitive) whose uuid is not one of the default-folder uuids.","commonSituations":"Users organizing custom folders try to name one 'Metrics' for their computed metrics, colliding with the reserved default. Imported folder trees that copied the default names without the default uuids.","solutions":["Rename the folder to something else ('My metrics', 'KPIs'), keeping the reserved words for the built-in folders.","If you intended to move items into the default metrics/columns folders, reference the default folder by its DEFAULT_FOLDER_UUIDS uuid instead of creating a new named node.","Check casing — the guard lowercases the name, so 'Metrics' is equally rejected."],"exampleFix":"# before\n{\"uuid\": \"<random>\", \"name\": \"Metrics\", \"children\": []}\n# after\n{\"uuid\": \"<random>\", \"name\": \"My metrics\", \"children\": []}","handlingStrategy":"validation","validationCode":"RESERVED = {\"metrics\", \"columns\"}\nDEFAULT_FOLDER_UUIDS = {...}  # from superset.constants / update module\n\nfor node in walk(folders):\n    name = (node.get(\"name\") or \"\").lower()\n    if name in RESERVED and str(node[\"uuid\"]) not in DEFAULT_FOLDER_UUIDS:\n        node[\"name\"] += \" (custom)\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat 'metrics'/'columns' as reserved regardless of casing.","Reference built-in folders by their default uuid, not by name.","Sanitize imported trees before replaying them."],"tags":["dataset","folders","validation","reserved-names"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}