usablica/intro.js · error

Provided callback for onbeforeexit was not a function.

Error message

Provided callback for onbeforeexit was not a function.

What it means

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.

Source

Thrown at src/packages/tour/tour.ts:662

    this.callbacks.skip = callback;
    return this;
  }

  /**
   * @deprecated onbeforeexit is deprecated, please use onBeforeExit instead.
   */
  onbeforeexit(callback: introBeforeExitCallback) {
    return this.onBeforeExit(callback);
  }

  /**
   * Add a callback to be called before the tour is exited
   * @param {Function} callback callback function to be called
   */
  onBeforeExit(callback: introBeforeExitCallback) {
    if (!isFunction(callback)) {
      throw new Error("Provided callback for onbeforeexit was not a function.");
    }

    this.callbacks.beforeExit = callback;
    return this;
  }
}

View on GitHub (pinned to e5517e6a24)

Solutions

  1. Pass an actual function reference: tour.onBeforeExit(() => { ... }).
  2. If the callback comes from a variable, check typeof cb === 'function' before registering, or fall back to a no-op.
  3. If you intended a function call's result, pass the function itself, not the invoked result.
  4. Verify the import/name of the callback — undefined from a bad import triggers this error.

Example fix

// before
const done = getCleanupHandler?.();
tour.onBeforeExit(done); // done may be undefined
// after
tour.onBeforeExit(() => getCleanupHandler?.());
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof cleanupFn !== 'function') {
  console.warn('onBeforeExit skipped: callback is not a function');
} else {
  tour.onBeforeExit(cleanupFn);
}

Type guard

function isFn(v: unknown): v is (...args: unknown[]) => unknown {
  return typeof v === 'function';
}

Try / catch

try {
  tour.onBeforeExit(cb);
} catch (e) {
  if (e.message.includes('onbeforeexit')) {
    console.error('Invalid onBeforeExit callback:', cb);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.


AI-assisted analysis of usablica/intro.js@e5517e6a24 (2026-08-31). Data as JSON: /api/errors/82ccd37423732463. Report an issue: GitHub.