{"record":{"id":"b9e3b65289231ca2","repo":"halo-dev/halo","slug":"menuname-is-required","errorCode":null,"errorMessage":"menuName is required.","messagePattern":"menuName is required\\.","errorType":"validation","errorClass":"ServerWebInputException","httpStatus":400,"severity":"warning","filePath":"application/src/main/java/run/halo/app/core/endpoint/console/MenuItemConsoleService.java","lineNumber":289,"sourceCode":"            if (item.getSpec() == null) {\n                item.setSpec(new MenuItem.MenuItemSpec());\n            }\n            item.getSpec().setParent(parentName);\n            item.getSpec().setPriority(i);\n        }\n    }\n\n    private static boolean hasHierarchyChanged(MenuItem item, HierarchyState original) {\n        if (original == null) {\n            return false;\n        }\n        return !Objects.equals(parentNameOf(item), original.parentName()) || priorityOf(item) != original.priority();\n    }\n\n    private static String normalizeRequired(String value, String message) {\n        var normalized = normalize(value);\n        if (normalized == null) {\n            throw new ServerWebInputException(message);\n        }\n        return normalized;\n    }\n\n    private static String normalize(String value) {\n        return org.springframework.util.StringUtils.hasText(value) ? value : null;\n    }\n\n    private record HierarchyState(String parentName, int priority) {}\n}\n","sourceCodeStart":271,"sourceCodeEnd":300,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/core/endpoint/console/MenuItemConsoleService.java#L271-L300","documentation":"MenuItemConsoleService.normalizeRequired(value, message) trims-and-checks a required string and throws ServerWebInputException (HTTP 400) with the supplied message when the value is blank. The 'menuName is required.' variant fires when the menu name for a menu item operation is missing — every menu item must belong to a menu.","triggerScenarios":"Creating or updating a menu item via the console endpoint without specifying which menu (menuName) it belongs to, or passing an empty/whitespace menuName.","commonSituations":"Frontend bug dropping the menuName field when saving a menu item; importing menu items without a menu reference; a plugin creating menu items programmatically and omitting the parent menu name.","solutions":["Always provide a non-blank menuName (the target menu's metadata.name) when creating/updating a menu item.","On the client, ensure a menu is selected before the item save action is enabled.","When importing, set menuName on every item before submission."],"exampleFix":"// before\nPOST /menu-items { \"spec\": { \"displayName\": \"Home\" } } // 400\n\n// after\nPOST /menu-items { \"spec\": { \"menuName\": \"main-menu\", \"displayName\": \"Home\" } }","handlingStrategy":"validation","validationCode":"if (!StringUtils.hasText(menuName)) {\n    return Mono.error(new ServerWebInputException(\"menuName is required.\"));\n}","typeGuard":"static boolean hasMenuName(String s) { return StringUtils.hasText(s); }","tryCatchPattern":null,"preventionTips":["Always set menuName when creating/updating a menu item.","Require a menu selection in the UI before enabling item save.","Set menuName on every item during import."],"tags":["validation","menu-item","http-400","required-field"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}