{"record":{"id":"38bd879549e5df0a","repo":"angular/components","slug":"expected-a-reference-to-the-parent-menu","errorCode":null,"errorMessage":"expected a reference to the parent menu","messagePattern":"expected a reference to the parent menu","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cdk/menu/menu-errors.ts","lineNumber":22,"sourceCode":" *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\n/**\n * Throws an exception when an instance of the PointerFocusTracker is not provided.\n * @docs-private\n */\nexport function throwMissingPointerFocusTracker() {\n  throw Error('expected an instance of PointerFocusTracker to be provided');\n}\n\n/**\n * Throws an exception when a reference to the parent menu is not provided.\n * @docs-private\n */\nexport function throwMissingMenuReference() {\n  throw Error('expected a reference to the parent menu');\n}\n","sourceCodeStart":4,"sourceCodeEnd":24,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/menu/menu-errors.ts#L4-L24","documentation":"Nested CDK menu directives need a reference to their parent menu. throwMissingMenuReference is raised from _checkConfigured when a child menu item/group cannot inject its parent cdkMenu/cdkMenuBar reference. It ensures the menu hierarchy (for keyboard navigation and positioning) is intact.","triggerScenarios":"Rendering cdkMenuItem or menu-group components outside any cdkMenu/cdkMenuBar ancestor; conditional templates (e.g. *ngIf, cdkOutlet) that detach the item from its parent menu context; dynamically created menu content that isn't within the menu's injector tree.","commonSituations":"Moving menu markup into a portal/overlay that loses the parent injector; a shared menu-item component reused outside menus; refactoring that removed the cdkMenu wrapper.","solutions":["Wrap the item in a cdkMenu or cdkMenuBar ancestor so the parent reference is injectable.","Use cdkMenuTrigger's attached menu template (ng-template cdkMenu) so the submenu stays in the correct context.","If rendering via portal, pass ViewContainerRef/Injector from the menu context so dependency injection resolves the parent menu.","Verify the DOM ancestry in devtools: the item must be inside the element carrying cdkMenu/cdkMenuBar."],"exampleFix":"// before\n<ng-container *ngIf=\"show\">\n  <button cdkMenuItem>Item</button> <!-- outside cdkMenu -->\n</ng-container>\n// after\n<div cdkMenu>\n  <ng-container *ngIf=\"show\">\n    <button cdkMenuItem>Item</button>\n  </ng-container>\n</div>","handlingStrategy":"try-catch","validationCode":"const parentMenu = injector.get(CdkMenu, null);\nif (!parentMenu) {\n  throw new Error('Menu item requires a parent cdkMenu/cdkMenuBar');\n}","typeGuard":"function isInMenuTree(el: HTMLElement): boolean {\n  return !!el.closest('[cdkMenu], [cdkMenuBar]');\n}","tryCatchPattern":"try {\n  this._checkConfigured();\n} catch (e) {\n  if ((e as Error).message.includes('parent menu')) {\n    console.error('Nest this item within a cdkMenu/cdkMenuBar.');\n  } else { throw e; }\n}","preventionTips":["Nest menu item/group directives under a cdkMenu or cdkMenuBar host.","Use cdkMenuTrigger's attached templates so submenus inherit the menu injector.","When portaling content, pass the menu's Injector/ViewContainerRef.","Review refactors that relocate menu markup for lost ancestry."],"tags":["angular","cdk","menu","dependency-injection"],"backgroundTag":"missing-menu-context","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}