{"record":{"id":"82ccd37423732463","repo":"usablica/intro.js","slug":"provided-callback-for-onbeforeexit-was-not-a-funct","errorCode":null,"errorMessage":"Provided callback for onbeforeexit was not a function.","messagePattern":"Provided callback for onbeforeexit was not a function\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/packages/tour/tour.ts","lineNumber":662,"sourceCode":"\n    this.callbacks.skip = callback;\n    return this;\n  }\n\n  /**\n   * @deprecated onbeforeexit is deprecated, please use onBeforeExit instead.\n   */\n  onbeforeexit(callback: introBeforeExitCallback) {\n    return this.onBeforeExit(callback);\n  }\n\n  /**\n   * Add a callback to be called before the tour is exited\n   * @param {Function} callback callback function to be called\n   */\n  onBeforeExit(callback: introBeforeExitCallback) {\n    if (!isFunction(callback)) {\n      throw new Error(\"Provided callback for onbeforeexit was not a function.\");\n    }\n\n    this.callbacks.beforeExit = callback;\n    return this;\n  }\n}\n","sourceCodeStart":644,"sourceCodeEnd":669,"githubUrl":"https://github.com/usablica/intro.js/blob/e5517e6a24e0530f87885af9fb2a69bafd1d4a6b/src/packages/tour/tour.ts#L644-L669","documentation":"Intro.js throws this from onBeforeExit() when the callback passed to it is not a function. The library stores the callback in this.callbacks.beforeExit and invokes it later during tour teardown, so a non-function value would crash at exit time; it fails fast at registration instead. Note the option-style setter is case-insensitive in message text only — the API method is onBeforeExit.","triggerScenarios":"Calling tour.onBeforeExit('cleanup') or tour.onBeforeExit(undefined) or tour.onBeforeExit(await someFn) where the value resolved to null/undefined, or passing a variable that was expected to hold a function but is undefined due to a typo or failed import.","commonSituations":"Passing the result of a function call instead of the function itself (e.g. onBeforeExit(stopTimer()) vs onBeforeExit(stopTimer)); referencing an optional callback from config that defaults to undefined; refactors renaming the callback so the variable no longer exists; misremembering the API as accepting an options object.","solutions":["Pass an actual function reference: tour.onBeforeExit(() => { ... }).","If the callback comes from a variable, check typeof cb === 'function' before registering, or fall back to a no-op.","If you intended a function call's result, pass the function itself, not the invoked result.","Verify the import/name of the callback — undefined from a bad import triggers this error."],"exampleFix":"// before\nconst done = getCleanupHandler?.();\ntour.onBeforeExit(done); // done may be undefined\n// after\ntour.onBeforeExit(() => getCleanupHandler?.());","handlingStrategy":"type-guard","validationCode":"if (typeof cleanupFn !== 'function') {\n  console.warn('onBeforeExit skipped: callback is not a function');\n} else {\n  tour.onBeforeExit(cleanupFn);\n}","typeGuard":"function isFn(v: unknown): v is (...args: unknown[]) => unknown {\n  return typeof v === 'function';\n}","tryCatchPattern":"try {\n  tour.onBeforeExit(cb);\n} catch (e) {\n  if (e.message.includes('onbeforeexit')) {\n    console.error('Invalid onBeforeExit callback:', cb);\n  } else throw e;\n}","preventionTips":["Always pass a function reference, never an invoked result.","Default optional callbacks to () => {} before registering.","Type the callback parameter as Function/() => void so TypeScript rejects non-functions at compile time.","Guard variables that may be undefined with optional checks before registering."],"tags":["type-error","callback","validation"],"backgroundTag":"callback-not-a-function","analyzedSha":"e5517e6a24e0530f87885af9fb2a69bafd1d4a6b","analyzedAt":"2026-08-31T22:12:26.007Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}