{"record":{"id":"07325bb52ee761d1","repo":"xpipe-io/xpipe","slug":"cannot-delete-category-cat-getname","errorCode":null,"errorMessage":"Cannot delete category: \" + cat.getName()","messagePattern":"Cannot delete category: \" \\+ cat\\.getName\\(\\)","errorType":"exception","errorClass":"BeaconClientException","httpStatus":400,"severity":"error","filePath":"app/src/main/java/io/xpipe/app/beacon/api/CategoryRemoveExchange.java","lineNumber":34,"sourceCode":"import java.util.UUID;\n\npublic class CategoryRemoveExchange extends BeaconInterface<CategoryRemoveExchange.Request> {\n\n    @Override\n    public String getPath() {\n        return \"/category/remove\";\n    }\n\n    @Override\n    public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {\n        var toRemove = new ArrayList<DataStoreCategory>();\n        for (UUID uuid : msg.getCategories()) {\n            var cat = DataStorage.get()\n                    .getStoreCategoryIfPresent(uuid)\n                    .orElseThrow(() -> new BeaconClientException(\"Unknown category: \" + uuid));\n\n            if (!DataStorage.get().canDeleteStoreCategory(cat)) {\n                throw new BeaconClientException(\"Cannot delete category: \" + cat.getName());\n            }\n\n            toRemove.add(cat);\n        }\n\n        for (DataStoreCategory cat : toRemove) {\n            DataStorage.get().deleteStoreCategory(cat, msg.isRemoveChildrenCategories(), msg.isRemoveContents());\n        }\n\n        return Response.builder().build();\n    }\n\n    @Override\n    public Object getSynchronizationObject() {\n        return DataStorage.get();\n    }\n\n    @Jacksonized","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/beacon/api/CategoryRemoveExchange.java#L16-L52","documentation":"XPipe's beacon API refuses to delete a data store category when DataStorage.canDeleteStoreCategory(cat) returns false. Certain categories are protected (e.g. built-in/default categories, or categories that still contain stores or sub-categories), so the daemon rejects removal instead of corrupting its storage hierarchy. The exception is a BeaconClientException, meaning it is reported back to the API client as a request-level failure.","triggerScenarios":"Calling the CategoryRemoveExchange beacon endpoint with a category UUID that resolves to a protected or non-empty category: a built-in default category, a category that still contains data stores, or one with child categories.","commonSituations":"Scripts or integrations that try to wipe all categories before a re-import; deleting the 'Default' or system category; removing a parent category without first moving or deleting its child stores and sub-categories; stale client-side caches listing categories that have become protected.","solutions":["Move or delete all data stores inside the category first, then retry the delete","Move or remove any child categories under it before deleting the parent","Check that the UUID is not one of XPipe's built-in/default categories and skip those","Call canDeleteStoreCategory (or an equivalent listing endpoint) beforehand and only request deletions that pass"],"exampleFix":"// before\nclient.removeCategories(List.of(anyUuid));\n// after\nfor (UUID uuid : uuids) {\n    if (DataStorage.get().canDeleteStoreCategory(DataStorage.get().getStoreCategoryIfPresent(uuid).orElseThrow())) {\n        client.removeCategories(List.of(uuid));\n    }\n}","handlingStrategy":"validation","validationCode":"DataStoreCategory cat = DataStorage.get().getStoreCategoryIfPresent(uuid).orElse(null);\nif (cat == null || !DataStorage.get().canDeleteStoreCategory(cat)) {\n    throw new IllegalStateException(\"Category \" + uuid + \" is protected or non-empty\");\n}","typeGuard":"boolean isDeletable(UUID uuid) {\n    return DataStorage.get().getStoreCategoryIfPresent(uuid)\n        .map(c -> DataStorage.get().canDeleteStoreCategory(c))\n        .orElse(false);\n}","tryCatchPattern":"try {\n    client.removeCategories(uuids);\n} catch (BeaconClientException e) {\n    if (e.getMessage().startsWith(\"Cannot delete category\")) {\n        logger.warn(\"Skipping protected category: \" + e.getMessage());\n    } else throw e;\n}","preventionTips":["Check canDeleteStoreCategory before each delete request","Empty the category (stores and child categories) before removal","Never attempt to delete built-in default categories"],"tags":["beacon-api","category-delete","validation"],"backgroundTag":"permission-denied","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}