nwjs/nw.js · error · TypeError

Invalid MenuItem type: {option.type}

Error message

Invalid MenuItem type: {option.type}

What it means

After defaulting a missing `type` to 'normal', MenuItem's constructor allows only 'normal', 'checkbox', and 'separator'. Any other value throws a TypeError that interpolates the offending type. macOS-only types like 'selector' are NOT in this whitelist despite being used internally by createMacBuiltin.

Source

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

// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

var v8_util = process.binding('v8_util');

function MenuItem(option) {
  if (typeof option != 'object')
    throw new TypeError('Invalid option.');

  if (!option.hasOwnProperty('type'))
    option.type = 'normal';

  if (option.type != 'normal' &&
      option.type != 'checkbox' &&
      option.type != 'separator')
    throw new TypeError('Invalid MenuItem type: ' + option.type);

  if (option.type == 'normal' || option.type == 'checkbox') {
    if (option.type == 'checkbox')
      option.checked = Boolean(option.checked);

    if (!option.hasOwnProperty('label'))
      throw new TypeError('A normal MenuItem must have a label');
    else
      option.label = String(option.label);

    if (option.hasOwnProperty('icon')) {
      option.shadowIcon = String(option.icon);
      option.icon = nw.getAbsolutePath(option.icon);
    }

    if (option.hasOwnProperty('iconIsTemplate'))
      option.iconIsTemplate = Boolean(option.iconIsTemplate);
    else

View on GitHub (pinned to e15da848e9)

Solutions

  1. Use one of the three allowed values: 'normal', 'checkbox', or 'separator'.
  2. If you need a submenu, use type 'normal' (the default) and set the `submenu` property to a Menu.
  3. For radio-like behavior, model it with 'checkbox' items and toggle siblings on click.

Example fix

// before
new nw.MenuItem({ type: 'radio', label: 'Opt' }); // throws

// after
new nw.MenuItem({ type: 'checkbox', label: 'Opt', checked: true });
Defensive patterns

Strategy: validation

Validate before calling

var TYPES = ['normal', 'checkbox', 'separator'];
function buildItem(opt) {
  opt = opt || {};
  if (opt.type && TYPES.indexOf(opt.type) === -1)
    throw new Error('Invalid MenuItem type: ' + opt.type);
  return new nw.MenuItem(opt);
}

Type guard

function isItemType(t) {
  return t === 'normal' || t === 'checkbox' || t === 'separator';
}

Try / catch

try { return new nw.MenuItem(opt); }
catch (e) {
  if (e instanceof TypeError && /Invalid MenuItem type/.test(e.message)) {
    delete opt.type; // let it default to 'normal'
    return new nw.MenuItem(opt);
  } throw e;
}

Prevention

When it happens

Trigger: Calling new nw.MenuItem({ type: 'radio' }), { type: 'submenu' }, or { type: 'check' }. Passing a misspelled value like 'checlbox' or 'Normal'.

Common situations: Developers coming from Electron's MenuItem (which has 'radio' and 'submenu' roles/​types). Typos. Assuming case-insensitivity ('Normal' throws).

Related errors


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