usablica/intro.js · error

Provided callback for oncomplete was not a function.

Error message

Provided callback for oncomplete was not a function.

What it means

Tour class onComplete registers the callback fired when the tour finishes, stored in this.callbacks.complete. It throws when isFunction(callback) is false, keeping later invocation safe. Note the error message uses the lowercase alias 'oncomplete'.

Source

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

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

  /**
   * @deprecated oncomplete is deprecated, please use onComplete instead.
   */
  oncomplete(callback: introCompleteCallback) {
    return this.onComplete(callback);
  }

  /**
   * Add a callback to be called when the tour is completed
   * @param {Function} callback callback function to be called
   */
  onComplete(callback: introCompleteCallback) {
    if (!isFunction(callback)) {
      throw new Error("Provided callback for oncomplete was not a function.");
    }

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

  /**
   * @deprecated onstart is deprecated, please use onStart instead.
   */
  onstart(callback: introStartCallback) {
    return this.onStart(callback);
  }

  /**
   * Add a callback to be called when the tour is started
   * @param {Function} callback callback function to be called
   */
  onStart(callback: introStartCallback) {

View on GitHub (pinned to e5517e6a24)

Solutions

  1. Pass a function: introJs().onComplete(function(){ ... }).
  2. Ensure the deprecated oncomplete alias (if used) also receives a function, or migrate to onComplete.
  3. Fix undefined handler variables (typos, load order, missing imports).
  4. Default optional callbacks: introJs().onComplete(cfg.done || (() => {})).
  5. Wrap setup in try/catch to identify the bad registration.

Example fix

// before
introJs().oncomplete(doneUrl); // string, not function
// after
introJs().onComplete(() => window.location.assign(doneUrl));
Defensive patterns

Strategy: validation

Validate before calling

if (typeof doneCb === 'function') { introJs().onComplete(doneCb); } else { introJs().onComplete(() => {}); }

Type guard

function isFn(v: unknown): v is () => void { return typeof v === 'function'; }

Try / catch

try {
  intro().onComplete(cb);
} catch (e) {
  if (/oncomplete was not a function/.test(e.message)) {
    intro().onComplete(() => {}); // swallow with fallback
  } else { throw e; }
}

Prevention

When it happens

Trigger: introJs().onComplete() with a non-function argument, or via the deprecated lowercase alias oncomplete passed a non-function.

Common situations: Migrating from intro.js's old lowercase alias API and passing the wrong thing; passing a routing navigation object; callback defined conditionally in code that skips its definition.

Related errors


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