{"record":{"id":"26512546bc56b897","repo":"nwjs/nw.js","slug":"listener-must-be-a-function-265125","errorCode":null,"errorMessage":"listener must be a function","messagePattern":"listener must be a function","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/resources/api_nw_window.js","lineNumber":178,"sourceCode":"      privates(this).menu = null;\n      this.onClose = bindingUtil.createCustomEvent(\"nw.Window.onClose\", true, false);\n      nwNatives.callInWindow(bgPage, \"__nw_initwindow\", currentRoutingID, this);\n    };\n    forEach(currentNWWindowInternal, function(key, value) {\n      if (!key.endsWith('Internal'))\n        NWWindow.prototype[key] = value;\n    });\n\n    NWWindow.prototype.onNewWinPolicy      = bindingUtil.createCustomEvent('nw.Window.onNewWinPolicy', false, false);\n    NWWindow.prototype.onNavigation        = bindingUtil.createCustomEvent('nw.Window.onNavigation', false, false);\n    NWWindow.prototype.LoadingStateChanged = bindingUtil.createCustomEvent('nw.Window.LoadingStateChanged', false, false);\n    NWWindow.prototype.onDocumentStart     = bindingUtil.createCustomEvent('nw.Window.onDocumentStart', false, false);\n    NWWindow.prototype.onDocumentEnd       = bindingUtil.createCustomEvent('nw.Window.onDocumentEnd', false, false);\n    NWWindow.prototype.onZoom              = bindingUtil.createCustomEvent('nw.Window.onZoom', false, false);\n\n    NWWindow.prototype.once = function (event, listener, record) {\n      if (typeof listener !== 'function')\n        throw new TypeError('listener must be a function');\n      var fired = false;\n      var self = this;\n\n      if (typeof record === 'undefined') {\n        nwNatives.callInWindow(bgPage, \"__nw_record_event\", this, event, listener, true);\n      }\n\n      function g() {\n        nwNatives.callInWindow(bgPage, \"__nw_removeOuterEventCB\", self, event, listener);\n        self.removeListener(event, g);\n        if (!fired) {\n          fired = true;\n          listener.apply(self, arguments);\n        }\n      }\n      this.on(event, g, false);\n      return this;\n    };","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/nwjs/nw.js/blob/e15da848e9e08e6e467532dae78995c6ad2f55ee/src/resources/api_nw_window.js#L160-L196","documentation":"Thrown by NWWindow.prototype.once(event, listener, record) when typeof listener !== 'function'. The once method wraps the listener to auto-remove after first fire and forwards it to the background page's event recording; a non-function listener cannot be invoked or recorded, so it is rejected upfront.","triggerScenarios":"win.once('loaded', null); win.once('close', undefined); win.once('focus', 'onFocus'); passing a config object instead of a callback.","commonSituations":"Optional callback patterns where the caller passes a possibly-undefined value without guarding; refactoring from on() to once() and forgetting to ensure the callback; JSON-loaded handler names.","solutions":["Guard the call: if (cb) win.once('loaded', cb);.","Pass a real function reference, not a name string.","Resolve handler names from a registry before calling once()."],"exampleFix":"// before\nwin.once('loaded', maybeCallback); // maybeCallback may be undefined\n// after\nif (typeof maybeCallback === 'function') win.once('loaded', maybeCallback);","handlingStrategy":"type-guard","validationCode":"if (typeof listener !== 'function') {\n  throw new TypeError('win.once listener must be a function');\n}\nwin.once(event, listener);","typeGuard":"function isListenerFn(fn) { return typeof fn === 'function'; }","tryCatchPattern":null,"preventionTips":["Guard optional callbacks: if (cb) win.once(event, cb).","Never pass handler name strings to once().","Resolve handler names from a registry before subscribing."],"tags":["nwjs","window","validation","event-listener","once"],"backgroundTag":null,"analyzedSha":"e15da848e9e08e6e467532dae78995c6ad2f55ee","analyzedAt":"2026-08-13T04:15:35.452Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}