{"record":{"id":"d60377a9cf5693d4","repo":"nwjs/nw.js","slug":"submenu-property-requries-a-valid-menu","errorCode":null,"errorMessage":"'submenu' property requries a valid Menu","messagePattern":"'submenu' property requries a valid Menu","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/api/menuitem/menuitem.js","lineNumber":184,"sourceCode":"\n  this.handleSetter('checked', 'SetChecked', Boolean, val);\n});\n\nMenuItem.prototype.__defineGetter__('enabled', function() {\n  return this.handleGetter('enabled');\n});\n\nMenuItem.prototype.__defineSetter__('enabled', function(val) {\n  this.handleSetter('enabled', 'SetEnabled', Boolean, val);\n});\n\nMenuItem.prototype.__defineGetter__('submenu', function() {\n  return v8_util.getHiddenValue(this, 'submenu');\n});\n\nMenuItem.prototype.__defineSetter__('submenu', function(val) {\n  if (v8_util.getConstructorName(val) != 'Menu')\n    throw new TypeError(\"'submenu' property requries a valid Menu\");\n\n  v8_util.setHiddenValue(this, 'submenu', val);\n  nw.callObjectMethod(this, 'SetSubmenu', [ val.id ]);\n});\n\nMenuItem.prototype.handleEvent = function(ev) {\n  if (ev == 'click') {\n    // Automatically flag the 'checked' property.\n    if (this.type == 'checkbox') {\n      var option = v8_util.getHiddenValue(this, 'option');\n      option.checked = !option.checked;\n    }\n\n    // Emit click handler\n    if (typeof this.click == 'function')\n      this.click();\n  }\n","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/nwjs/nw.js/blob/e15da848e9e08e6e467532dae78995c6ad2f55ee/src/api/menuitem/menuitem.js#L166-L202","documentation":"The runtime `submenu` setter (distinct from the constructor-time check) throws a TypeError if the value's constructor name is not 'Menu'. On success it stashes the Menu in a hidden value and calls the native SetSubmenu with the Menu's id. The message contains a typo (\"requries\").","triggerScenarios":"Assigning `item.submenu = []`, `item.submenu = otherItem`, or `item.submenu = null` at runtime. Passing a Menu from a different JS realm.","commonSituations":"Dynamically swapping submenus at runtime (e.g., rebuilding a recent-files list). Developers assign an array of items expecting auto-conversion. Clearing a submenu by assigning null.","solutions":["Build a nw.Menu instance and assign that: `item.submenu = new nw.Menu();`.","To clear, assign an empty nw.Menu rather than null or [].","Rebuild child items into the new Menu before attaching."],"exampleFix":"// before\nitem.submenu = [{ label: 'Recent' }]; // throws\nitem.submenu = null;                   // throws\n\n// after\nvar recent = new nw.Menu();\nrecent.append(new nw.MenuItem({ label: 'Recent' }));\nitem.submenu = recent;","handlingStrategy":"type-guard","validationCode":"function setSubmenu(item, submenu) {\n  if (submenu && !(submenu instanceof nw.Menu))\n    throw new TypeError('submenu must be a nw.Menu');\n  item.submenu = submenu;\n}","typeGuard":"function isMenu(v) {\n  return v instanceof nw.Menu ||\n    (v && typeof v === 'object' && v.constructor && v.constructor.name === 'Menu');\n}","tryCatchPattern":"try { item.submenu = val; }\ncatch (e) {\n  if (e instanceof TypeError && /submenu.*valid Menu/.test(e.message)) {\n    var m = new nw.Menu();\n    item.submenu = m; // assign a real (possibly empty) Menu\n  } else throw e;\n}","preventionTips":["Always assign a nw.Menu instance to submenu.","To clear, assign an empty nw.Menu, not null or [].","Rebuild child items before attaching the new submenu."],"tags":["nwjs","menuitem","submenu","type-validation","immutable-adjacent"],"backgroundTag":null,"analyzedSha":"e15da848e9e08e6e467532dae78995c6ad2f55ee","analyzedAt":"2026-08-13T04:15:35.452Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}