nwjs/nw.js · error · TypeError
Menu.append() requires a valid MenuItem
Error message
Menu.append() requires a valid MenuItem
What it means
Menu.prototype.append checks that the argument's constructor name is exactly 'MenuItem' before pushing it onto the items array and calling the native Append. Anything else — a plain object, a string, an element from another frame — is rejected with a TypeError to protect the native call that dereferences menu_item.id.
Source
Thrown at src/api/menu/menu.js:48
throw new TypeError('Invalid menu type: ' + option.type);
this.type = option.type;
v8_util.setHiddenValue(this, 'items', []);
nw.allocateObject(this, option);
}
require('util').inherits(Menu, exports.Base);
Menu.prototype.__defineGetter__('items', function() {
return v8_util.getHiddenValue(this, 'items');
});
Menu.prototype.__defineSetter__('items', function(val) {
throw new Error('Menu.items is immutable');
});
Menu.prototype.append = function(menu_item) {
if (v8_util.getConstructorName(menu_item) != 'MenuItem')
throw new TypeError("Menu.append() requires a valid MenuItem");
this.items.push(menu_item);
nw.callObjectMethod(this, 'Append', [ menu_item.id ]);
};
Menu.prototype.insert = function(menu_item, i) {
this.items.splice(i, 0, menu_item);
nw.callObjectMethod(this, 'Insert', [ menu_item.id, i ]);
}
Menu.prototype.remove = function(menu_item) {
var pos_hint = this.items.indexOf(menu_item);
nw.callObjectMethod(this, 'Remove', [ menu_item.id, pos_hint ]);
this.items.splice(pos_hint, 1);
}
Menu.prototype.removeAt = function(i) {
nw.callObjectMethod(this, 'Remove', [ this.items[i].id, i ]);View on GitHub (pinned to e15da848e9)
Solutions
- Wrap each entry with `new nw.MenuItem({ label: 'x', click: fn })` before appending.
- Use a helper that always constructs MenuItem instances.
- If sharing across frames, construct the items in the same context that owns the Menu.
Example fix
// before
menu.append({ label: 'Open', click: onOpen }); // throws
// after
menu.append(new nw.MenuItem({ label: 'Open', click: onOpen })); Defensive patterns
Strategy: type-guard
Validate before calling
function appendItem(menu, item) {
if (!(item instanceof nw.MenuItem))
item = new nw.MenuItem(item);
menu.append(item);
} Type guard
function isMenuItem(v) {
return v instanceof nw.MenuItem ||
(v && typeof v === 'object' && v.constructor && v.constructor.name === 'MenuItem');
} Try / catch
try { menu.append(item); }
catch (e) {
if (e instanceof TypeError && /valid MenuItem/.test(e.message)) {
menu.append(new nw.MenuItem(item));
} else throw e;
} Prevention
- Always wrap entries with new nw.MenuItem(...).
- Use a helper that coerces plain objects to MenuItem.
- Construct items in the same context as the Menu.
When it happens
Trigger: Calling menu.append({label:'x'}), menu.append('label'), or menu.append(someTrayItem). Also a MenuItem created in another context whose constructor name does not match.
Common situations: Developers build menu entries as plain option objects and forget to wrap them with `new nw.MenuItem(...)`. Mixing up MenuItem with Tray or other API objects. Cross-frame menu construction.
Related errors
- 'submenu' must be a valid Menu
- 'click' must be a valid Function
- 'submenu' property requries a valid Menu
- Invaild parameter, need Shortcut object.
- Type of '{type}' is not supported
AI-assisted analysis of nwjs/nw.js@e15da848e9 (2026-08-13).
Data as JSON: /api/errors/5ae1fcf199ba5823.
Report an issue: GitHub.