{"record":{"id":"07255dc6d147b7ab","repo":"usablica/intro.js","slug":"provided-callback-for-oncomplete-was-not-a-functio","errorCode":null,"errorMessage":"Provided callback for oncomplete was not a function.","messagePattern":"Provided callback for oncomplete was not a function\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/packages/tour/tour.ts","lineNumber":582,"sourceCode":"\n    this.callbacks.afterChange = callback;\n    return this;\n  }\n\n  /**\n   * @deprecated oncomplete is deprecated, please use onComplete instead.\n   */\n  oncomplete(callback: introCompleteCallback) {\n    return this.onComplete(callback);\n  }\n\n  /**\n   * Add a callback to be called when the tour is completed\n   * @param {Function} callback callback function to be called\n   */\n  onComplete(callback: introCompleteCallback) {\n    if (!isFunction(callback)) {\n      throw new Error(\"Provided callback for oncomplete was not a function.\");\n    }\n\n    this.callbacks.complete = callback;\n    return this;\n  }\n\n  /**\n   * @deprecated onstart is deprecated, please use onStart instead.\n   */\n  onstart(callback: introStartCallback) {\n    return this.onStart(callback);\n  }\n\n  /**\n   * Add a callback to be called when the tour is started\n   * @param {Function} callback callback function to be called\n   */\n  onStart(callback: introStartCallback) {","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/usablica/intro.js/blob/e5517e6a24e0530f87885af9fb2a69bafd1d4a6b/src/packages/tour/tour.ts#L564-L600","documentation":"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'.","triggerScenarios":"introJs().onComplete() with a non-function argument, or via the deprecated lowercase alias oncomplete passed a non-function.","commonSituations":"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.","solutions":["Pass a function: introJs().onComplete(function(){ ... }).","Ensure the deprecated oncomplete alias (if used) also receives a function, or migrate to onComplete.","Fix undefined handler variables (typos, load order, missing imports).","Default optional callbacks: introJs().onComplete(cfg.done || (() => {})).","Wrap setup in try/catch to identify the bad registration."],"exampleFix":"// before\nintroJs().oncomplete(doneUrl); // string, not function\n// after\nintroJs().onComplete(() => window.location.assign(doneUrl));","handlingStrategy":"validation","validationCode":"if (typeof doneCb === 'function') { introJs().onComplete(doneCb); } else { introJs().onComplete(() => {}); }","typeGuard":"function isFn(v: unknown): v is () => void { return typeof v === 'function'; }","tryCatchPattern":"try {\n  intro().onComplete(cb);\n} catch (e) {\n  if (/oncomplete was not a function/.test(e.message)) {\n    intro().onComplete(() => {}); // swallow with fallback\n  } else { throw e; }\n}","preventionTips":["Use the modern camelCase onComplete API","Do not pass URLs/strings expecting the library to navigate; wrap in a function","Confirm callback variables are assigned at registration time","Keep callback wiring adjacent to introJs() creation"],"tags":["callbacks","type-validation","api-misuse"],"backgroundTag":"callback-not-a-function","analyzedSha":"e5517e6a24e0530f87885af9fb2a69bafd1d4a6b","analyzedAt":"2026-08-31T22:12:26.007Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}