nwjs/nw.js · error · TypeError

A normal MenuItem must have a label

Error message

A normal MenuItem must have a label

What it means

For types 'normal' and 'checkbox', the constructor enforces that a `label` property exists (via hasOwnProperty) before coercing it with String(). A normal/checkbox item without a label throws a TypeError. Separator type is exempt because it takes a different branch that discards all other options.

Source

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

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
      option.iconIsTemplate = true;

    if (option.hasOwnProperty('tooltip'))
      option.tooltip = String(option.tooltip);

    if (option.hasOwnProperty('enabled'))
      option.enabled = Boolean(option.enabled);

View on GitHub (pinned to e15da848e9)

Solutions

  1. Add a `label` property to the option: `new nw.MenuItem({ type: 'normal', label: 'Open' })`.
  2. If you want a blank label, pass an empty string explicitly ({ label: '' }).
  3. For divider items, use type: 'separator' instead.

Example fix

// before
new nw.MenuItem({ type: 'normal', icon: 'open.png' }); // throws

// after
new nw.MenuItem({ type: 'normal', label: 'Open', icon: 'open.png' });
Defensive patterns

Strategy: validation

Validate before calling

function buildItem(opt) {
  if ((!opt.type || opt.type === 'normal' || opt.type === 'checkbox') &&
      !opt.hasOwnProperty('label')) {
    opt.label = ''; // or a real label
  }
  return new nw.MenuItem(opt);
}

Type guard

function itemHasRequiredLabel(opt) {
  var needsLabel = !opt.type || opt.type === 'normal' || opt.type === 'checkbox';
  return !needsLabel || opt.hasOwnProperty('label');
}

Try / catch

try { return new nw.MenuItem(opt); }
catch (e) {
  if (e instanceof TypeError && /must have a label/.test(e.message)) {
    opt.label = opt.label || '';
    return new nw.MenuItem(opt);
  } throw e;
}

Prevention

When it happens

Trigger: Calling new nw.MenuItem({ type: 'normal' }) with no label, or { type: 'checkbox', checked: true }) without label. Setting label to undefined explicitly ({label: undefined}) also throws because hasOwnProperty('label') is true but the value is undefined.

Common situations: Building an icon-only menu item (the API does not support label-less normal items). Forgetting the label when adding a checkbox. Refactoring that strips the label field conditionally.

Related errors


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