{"record":{"id":"7ecae4820f45c110","repo":"nwjs/nw.js","slug":"menu-items-is-immutable-7ecae4","errorCode":null,"errorMessage":"Menu.items is immutable","messagePattern":"Menu\\.items is immutable","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/resources/api_nw_menu.js","lineNumber":33,"sourceCode":"  var id = nw.Obj.allocateId();\n  option.generatedId = id;\n\n  this.id = id;\n  this.type = option.type;\n  privates(this).items = [];\n  privates(this).option = option;\n\n  var items = privates(this).items;\n  nw.Obj.create(id, 'Menu', option);\n  messagingNatives.BindToGC(this, function() { items.forEach(function(element) { element._destroy(); }); nw.Obj.destroy(id); });\n};\n\nMenu.prototype.__defineGetter__('items', function() {\n  return privates(this).items;\n});\n\nMenu.prototype.__defineSetter__('items', function(val) {\n  throw new Error('Menu.items is immutable');\n});\n\nMenu.prototype.append = function(menu_item) {\n  privates(this).items.push(menu_item);\n  if (!menu_item.native)\n    nw.Obj.callObjectMethod(this.id, 'Menu', 'Append', [ menu_item.id ]);\n};\n\nMenu.prototype.insert = function(menu_item, i) {\n  privates(this).items.splice(i, 0, menu_item);\n  if (!menu_item.native)\n    nw.Obj.callObjectMethod(this.id, 'Menu', 'Insert', [ menu_item.id, i ]);\n}\n\nMenu.prototype.remove = function(menu_item) {\n  var pos_hint = privates(this).items.indexOf(menu_item);\n  nw.Obj.callObjectMethod(this.id, 'Menu', 'Remove', [ menu_item.id, pos_hint ]);\n  privates(this).items.splice(pos_hint, 1);","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/nwjs/nw.js/blob/e15da848e9e08e6e467532dae78995c6ad2f55ee/src/resources/api_nw_menu.js#L15-L51","documentation":"Thrown by the Menu 'items' setter whenever a value is assigned to menu.items. The items collection is backed by privates(this).items and is only mutated through append/insert/remove; direct replacement is forbidden because it would desync the JS array from the native menu.","triggerScenarios":"Running `menu.items = [item1, item2]` or `menu.items = newArray` to rebuild the menu.","commonSituations":"Attempting to reset a menu by reassigning items as you would an ordinary array.","solutions":["Clear and re-append: remove existing items via remove() then append() each new one.","Create a fresh Menu instance and replace the reference where it is consumed (e.g. tray.menu)."],"exampleFix":"// before\nmenu.items = [new nw.MenuItem({ label: 'a' })];\n// after\nwhile (menu.items.length) menu.remove(menu.items[0]);\nmenu.append(new nw.MenuItem({ label: 'a' }));","handlingStrategy":"validation","validationCode":"// never assign to menu.items; mutate via append/insert/remove only","typeGuard":"function isMenuItemArray(v) { return Array.isArray(v) && v.every(i => i && i.constructor && i.constructor.name === 'MenuItem'); }","tryCatchPattern":"try { menu.items = arr; } catch (e) { if (/immutable/.test(e.message)) { while (menu.items.length) menu.remove(menu.items[0]); arr.forEach(i => menu.append(i)); } else throw e; }","preventionTips":["Treat menu.items as read-only.","Build a rebuild helper that removes then re-appends."],"tags":["menu","immutable","setter","nwjs"],"backgroundTag":null,"analyzedSha":"e15da848e9e08e6e467532dae78995c6ad2f55ee","analyzedAt":"2026-08-13T04:15:35.452Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}