nwjs/nw.js · error · TypeError
'submenu' property requries a valid Menu
Error message
'submenu' property requries a valid Menu
What it means
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").
Source
Thrown at src/api/menuitem/menuitem.js:184
this.handleSetter('checked', 'SetChecked', Boolean, val);
});
MenuItem.prototype.__defineGetter__('enabled', function() {
return this.handleGetter('enabled');
});
MenuItem.prototype.__defineSetter__('enabled', function(val) {
this.handleSetter('enabled', 'SetEnabled', Boolean, val);
});
MenuItem.prototype.__defineGetter__('submenu', function() {
return v8_util.getHiddenValue(this, 'submenu');
});
MenuItem.prototype.__defineSetter__('submenu', function(val) {
if (v8_util.getConstructorName(val) != 'Menu')
throw new TypeError("'submenu' property requries a valid Menu");
v8_util.setHiddenValue(this, 'submenu', val);
nw.callObjectMethod(this, 'SetSubmenu', [ val.id ]);
});
MenuItem.prototype.handleEvent = function(ev) {
if (ev == 'click') {
// Automatically flag the 'checked' property.
if (this.type == 'checkbox') {
var option = v8_util.getHiddenValue(this, 'option');
option.checked = !option.checked;
}
// Emit click handler
if (typeof this.click == 'function')
this.click();
}
View on GitHub (pinned to e15da848e9)
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.
Example fix
// before
item.submenu = [{ label: 'Recent' }]; // throws
item.submenu = null; // throws
// after
var recent = new nw.Menu();
recent.append(new nw.MenuItem({ label: 'Recent' }));
item.submenu = recent; Defensive patterns
Strategy: type-guard
Validate before calling
function setSubmenu(item, submenu) {
if (submenu && !(submenu instanceof nw.Menu))
throw new TypeError('submenu must be a nw.Menu');
item.submenu = submenu;
} Type guard
function isMenu(v) {
return v instanceof nw.Menu ||
(v && typeof v === 'object' && v.constructor && v.constructor.name === 'Menu');
} Try / catch
try { item.submenu = val; }
catch (e) {
if (e instanceof TypeError && /submenu.*valid Menu/.test(e.message)) {
var m = new nw.Menu();
item.submenu = m; // assign a real (possibly empty) Menu
} else throw e;
} Prevention
- 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.
When it happens
Trigger: Assigning `item.submenu = []`, `item.submenu = otherItem`, or `item.submenu = null` at runtime. Passing a Menu from a different JS realm.
Common situations: 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.
Related errors
- 'submenu' must be a valid Menu
- Menu.append() requires a valid MenuItem
- 'click' must be a valid Function
- 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/d60377a9cf5693d4.
Report an issue: GitHub.