{"record":{"id":"af2a057213dfa629","repo":"nwjs/nw.js","slug":"type-is-immutable-at-runtime-af2a05","errorCode":null,"errorMessage":"'type' is immutable at runtime","messagePattern":"'type' is immutable at runtime","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/resources/api_nw_menuitem.js","lineNumber":121,"sourceCode":"\nutil.inherits(MenuItem, EventEmitter);\n\nMenuItem.prototype.handleGetter = function(name) {\n  return privates(this).option[name];\n};\n\nMenuItem.prototype.handleSetter = function(name, setter, type, value) {\n  value = type(value);\n  privates(this).option[name] = value;\n  nw.Obj.callObjectMethod(this.id, 'MenuItem', setter, [ value ]);\n};\n\nMenuItem.prototype.__defineGetter__('type', function() {\n  return this.handleGetter('type');\n});\n\nMenuItem.prototype.__defineSetter__('type', function() {\n  throw new Error(\"'type' is immutable at runtime\");\n});\n\nMenuItem.prototype.__defineGetter__('label', function() {\n  return this.handleGetter('label');\n});\n\nMenuItem.prototype.__defineSetter__('label', function(val) {\n  this.handleSetter('label', 'SetLabel', String, val);\n});\n\nMenuItem.prototype.__defineGetter__('icon', function() {\n  return this.handleGetter('shadowIcon');\n});\n\nMenuItem.prototype.__defineSetter__('icon', function(val) {\n  privates(this).option.shadowIcon = String(val);\n  var real_path = val == '' ? '' : nwNative.getAbsolutePath(val); //FIXME\n  this.handleSetter('icon', 'SetIcon', String, real_path);","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/nwjs/nw.js/blob/e15da848e9e08e6e467532dae78995c6ad2f55ee/src/resources/api_nw_menuitem.js#L103-L139","documentation":"Thrown by the MenuItem 'type' setter whenever any value is assigned. The native menu item is created with a fixed type at construction; changing type (e.g. normal to separator) is not supported and would invalidate the native object, so the setter always throws.","triggerScenarios":"Running `item.type = 'separator'`, `item.type = 'checkbox'`, or any assignment to .type after construction.","commonSituations":"Trying to toggle an item between a normal entry and a divider dynamically; porting UI code that mutated type.","solutions":["Create a new MenuItem of the desired type and replace it in the menu (append the new one, remove the old).","To hide an item, use item.visible = false rather than changing its type."],"exampleFix":"// before\nitem.type = 'separator';\n// after\nconst sep = new nw.MenuItem({ type: 'separator' });\nmenu.insert(sep, menu.items.indexOf(item));\nmenu.remove(item);","handlingStrategy":"validation","validationCode":"// never assign to item.type; rebuild the item instead","typeGuard":"function isMutableMenuItemProp(p) { return ['label', 'icon', 'enabled', 'checked', 'tooltip', 'modifiers'].indexOf(p) !== -1; }","tryCatchPattern":"try { item.type = t; } catch (e) { if (/immutable/.test(e.message)) console.warn('type is immutable; rebuild the item'); else throw e; }","preventionTips":["Treat type as constructor-only.","Replace items in the menu instead of mutating their type."],"tags":["menuitem","immutable","setter","nwjs"],"backgroundTag":null,"analyzedSha":"e15da848e9e08e6e467532dae78995c6ad2f55ee","analyzedAt":"2026-08-13T04:15:35.452Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}