nwjs/nw.js · error · Error

'type' is immutable at runtime

Error message

'type' is immutable at runtime

What it means

MenuItem defines a `type` setter that unconditionally throws a plain Error — type is fixed at construction and cannot be changed at runtime. The getter reads from the hidden option object via handleGetter. Reassigning menuItem.type (even to the same value) trips the setter.

Source

Thrown at src/api/menuitem/menuitem.js:103

  if (!option.hasOwnProperty('icon'))
    option.shadowIcon = '';
  if (!option.hasOwnProperty('tooltip'))
    option.tooltip = '';
  if (!option.hasOwnProperty('enabled'))
    option.enabled = true;
  if (!option.hasOwnProperty('key'))
    option.key = "";
  if (!option.hasOwnProperty('modifiers'))
    option.modifiers = "";
}
require('util').inherits(MenuItem, exports.Base);

MenuItem.prototype.__defineGetter__('type', function() {
  return this.handleGetter('type');
});

MenuItem.prototype.__defineSetter__('type', function() {
  throw new Error("'type' is immutable at runtime");
});

MenuItem.prototype.__defineGetter__('label', function() {
  return this.handleGetter('label');
});

MenuItem.prototype.__defineSetter__('label', function(val) {
  this.handleSetter('label', 'SetLabel', String, val);
});

MenuItem.prototype.__defineGetter__('icon', function() {
  return this.handleGetter('shadowIcon');
});

MenuItem.prototype.__defineSetter__('icon', function(val) {
  v8_util.getHiddenValue(this, 'option').shadowIcon = String(val);
  var real_path = val == '' ? '' : nw.getAbsolutePath(val);
  this.handleSetter('icon', 'SetIcon', String, real_path);

View on GitHub (pinned to e15da848e9)

Solutions

  1. Create a new MenuItem with the desired type and replace the old one in the menu.
  2. If you only need toggle UI, use type 'checkbox' from the start and flip the `checked` property.
  3. Avoid generic property-copy loops that write back `type`.

Example fix

// before
item.type = 'checkbox'; // throws

// after
menu.remove(item);
var toggler = new nw.MenuItem({ type: 'checkbox', label: item.label, checked: true, click: item.click });
menu.append(toggler);
Defensive patterns

Strategy: validation

Validate before calling

// type is set-once: never reassign it.
function changeItemType(menu, item, newType) {
  var opt = { type: newType, label: item.label, click: item.click };
  if (item.icon) opt.icon = item.icon;
  var next = new nw.MenuItem(opt);
  var pos = menu.items.indexOf(item);
  menu.remove(item);
  menu.insert(next, pos);
}

Try / catch

try { item.type = newType; }
catch (e) {
  if (e instanceof Error && /immutable/.test(e.message)) {
    throw new Error('Cannot change item.type at runtime; rebuild the item.');
  } throw e;
}

Prevention

When it happens

Trigger: Any assignment to `menuItem.type`, e.g. `item.type = 'checkbox'` or `item.type = item.type`. Also attempts to toggle a normal item into a checkbox at runtime.

Common situations: Developers try to mutate item kind dynamically (e.g., switching between normal and checkbox based on state). Code that defensively reassigns properties after load. Copy/restore patterns that iterate and write all properties.

Related errors


AI-assisted analysis of nwjs/nw.js@e15da848e9 (2026-08-13). Data as JSON: /api/errors/3dc22b0f2041eeb3. Report an issue: GitHub.