{"record":{"id":"9d81eb143bf0f096","repo":"NativeScript/NativeScript","slug":"callback-if-provided-must-be-function","errorCode":null,"errorMessage":"Callback, if provided, must be function.","messagePattern":"Callback, if provided, must be function\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/data/observable/index.ts","lineNumber":341,"sourceCode":"\t\t\tentries.splice(i, 1);\n\t\t\ti--;\n\t\t}\n\t}\n\n\t/**\n\t * Please avoid using the static event-handling APIs as they will be removed\n\t * in future.\n\t * @deprecated\n\t */\n\tpublic static removeEventListener(eventName: string, callback?: (data: EventData) => void, thisArg?: any): void {\n\t\tthisArg = thisArg || undefined;\n\n\t\tif (typeof eventName !== 'string') {\n\t\t\tthrow new TypeError('Event name must be a string.');\n\t\t}\n\n\t\tif (callback && typeof callback !== 'function') {\n\t\t\tthrow new TypeError('Callback, if provided, must be function.');\n\t\t}\n\n\t\tconst eventClass = this.name === 'Observable' ? '*' : this.name;\n\n\t\tconst entries = _globalEventHandlers?.[eventClass]?.[eventName];\n\t\tif (!entries) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst countBeforeRemoval = entries.length;\n\t\tObservable.innerRemoveEventListener(entries, callback, thisArg);\n\t\t_globalEventHandlersCount -= countBeforeRemoval - entries.length;\n\n\t\tif (!entries.length) {\n\t\t\t// Clear all entries of this type\n\t\t\tdelete _globalEventHandlers[eventClass][eventName];\n\t\t}\n","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/NativeScript/NativeScript/blob/6800aefa6511d23ddad8beb38ccc8541c5e91628/packages/core/data/observable/index.ts#L323-L359","documentation":"The static Observable.removeEventListener throws this TypeError when a truthy `callback` argument is provided that is not a function. Like the instance variant, it validates types before touching the global handler registry.","triggerScenarios":"Calling `Observable.off('eventName', someObject)` or the deprecated static removeEventListener with a non-function second argument while unsubscribing from class-level (global) events.","commonSituations":"Passing an event emitter, promise, or config object where the handler belongs; stale imports where the handler name refers to a non-callable export.","solutions":["Pass the original function reference used with static addEventListener","If no callback is needed, omit the second argument entirely","Add a `typeof cb === 'function'` check before calling"],"exampleFix":"// before\nObservable.off('loaded', this.handlers['loaded']);\n// after\nconst cb = this.handlers['loaded'];\nif (typeof cb === 'function') Observable.off('loaded', cb);","handlingStrategy":"type-guard","validationCode":"if (callback === undefined || typeof callback === 'function') Observable.removeEventListener(eventName, callback);","typeGuard":"const isHandler = (v: unknown): v is (data: import('@nativescript/core').EventData) => void => typeof v === 'function';","tryCatchPattern":"try { Observable.off(name, cb); } catch (e) { if (e instanceof TypeError) { /* drop bad handler ref, resubscribe */ } else throw e; }","preventionTips":["Store handler references at subscribe time and reuse them for off()","Validate dynamically-supplied handlers with typeof","Avoid the deprecated static API where possible"],"tags":["events","typeerror","observable"],"backgroundTag":"callback-not-a-function","analyzedSha":"6800aefa6511d23ddad8beb38ccc8541c5e91628","analyzedAt":"2026-08-30T20:04:56.809Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}