usablica/intro.js · error

Provided callback for onChange was not a function.

Error message

Provided callback for onChange was not a function.

What it means

Tour class onChange registers the per-step-change callback into this.callbacks.change. It validates the argument with isFunction and throws when it is not a function, so the tour's internal call site can invoke it unconditionally.

Source

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

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

  /**
   * @deprecated onchange is deprecated, please use onChange instead.
   */
  onchange(callback: introChangeCallback) {
    this.onChange(callback);
  }

  /**
   * Add a callback to be called when the tour changes steps
   * @param {Function} callback callback function to be called
   */
  onChange(callback: introChangeCallback) {
    if (!isFunction(callback)) {
      throw new Error("Provided callback for onChange was not a function.");
    }

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

  /**
   * @deprecated onafterchange is deprecated, please use onAfterChange instead.
   */
  onafterchange(callback: introAfterChangeCallback) {
    this.onAfterChange(callback);
  }

  /**
   * Add a callback to be called after the tour changes steps
   * @param {Function} callback callback function to be called
   */
  onAfterChange(callback: introAfterChangeCallback) {

View on GitHub (pinned to e5517e6a24)

Solutions

  1. Pass a function: introJs().onChange(function(targetElement){ ... }).
  2. Verify typeof the argument is 'function' right before the call and trace back why it isn't.
  3. Register callbacks after module/config initialization completes.
  4. Use a no-op fallback: introJs().onChange(config.onChange || function(){}).
  5. Catch the error to log which setup step was misconfigured.

Example fix

// before
introJs().onChange(await loadHandler()); // Promise, not function
// after
const handler = await loadHandler();
introJs().onChange(() => handler());
Defensive patterns

Strategy: validation

Validate before calling

if (typeof changeCb !== 'function') changeCb = () => {};
introJs().onChange(changeCb);

Type guard

function isFunction(v: unknown): v is Function { return typeof v === 'function'; }

Try / catch

try {
  introJs().onChange(cb);
} catch (e) {
  if (/onChange was not a function/.test(e.message)) {
    introJs().onChange(() => {});
  } else { throw e; }
}

Prevention

When it happens

Trigger: introJs().onChange() with no argument or a non-function value (undefined variable, Promise, object) — commonly from an options object wired to the wrong key.

Common situations: Passing the result of an async function (a Promise) instead of a function; SSR frameworks where the handler module isn't loaded; renaming handlers and missing one call site.

Related errors


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