{"record":{"id":"830e4ecb0940a88a","repo":"appsmithorg/appsmith","slug":"onready-expects-a-function-as-parameter-830e4e","errorCode":null,"errorMessage":"onReady expects a function as parameter","messagePattern":"onReady expects a function as parameter","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/client/src/widgets/wds/WDSCustomWidget/component/customWidgetscript.js","lineNumber":266,"sourceCode":"          channel.postMessage(EVENTS.CUSTOM_WIDGET_UPDATE_MODEL, obj);\n        },\n        triggerEvent: (eventName, contextObj) => {\n          if (typeof eventName !== \"string\") {\n            throw new Error(\"eventName should be a string\");\n          } else if (contextObj && typeof contextObj !== \"object\") {\n            throw new Error(\"contextObj should be an object\");\n          }\n\n          // Send a trigger event message to the parent\n          channel.postMessage(EVENTS.CUSTOM_WIDGET_TRIGGER_EVENT, {\n            eventName,\n            contextObj,\n          });\n        },\n        model: {},\n        onReady: (fn) => {\n          if (typeof fn !== \"function\") {\n            throw new Error(\"onReady expects a function as parameter\");\n          }\n\n          onReady = fn;\n\n          if (isReady && !isReadyCalled && onReady) {\n            onReady();\n            isReadyCalled = true;\n          }\n        },\n      },\n    });\n  }\n\n  // Listen for the 'load' event and send READY message to the parent\n  window.addEventListener(\"load\", () => {\n    channel.postMessage(EVENTS.CUSTOM_WIDGET_READY);\n  });\n}","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/appsmithorg/appsmith/blob/8cd9021c24cdbea1c3c12c966073708e83db60c2/app/client/src/widgets/wds/WDSCustomWidget/component/customWidgetscript.js#L248-L284","documentation":"Thrown by window.appsmith.onReady() in the WDS Custom Widget iframe. onReady stores a single readiness callback (onReady = fn) and invokes it synchronously if the host has already signalled readiness and it has not been called yet. A non-function argument is rejected because the method may immediately invoke it.","triggerScenarios":"Calling appsmith.onReady(undefined), appsmith.onReady(null), appsmith.onReady('init'), appsmith.onReady({bootstrap:fn}), or appsmith.onReady() with no argument in the WDS widget.","commonSituations":"Invoking the init function instead of passing it; passing a config object containing the handler; calling onReady twice and omitting the argument the second time.","solutions":["Pass the function reference: appsmith.onReady(bootstrap).","Use an inline arrow: appsmith.onReady(() => mount(appsmith.model)).","Keep the callback idempotent; only the last registered one is retained.","Do bootstrap work inside the callback, not at top-level, so the host channel is ready."],"exampleFix":"// before\nappsmith.onReady(init()); // invokes init, passes undefined\n\n// after\nappsmith.onReady(init); // passes the function reference","handlingStrategy":"type-guard","validationCode":"if (typeof readyHandler !== 'function') {\n  throw new TypeError('onReady expects a function');\n}\nappsmith.onReady(readyHandler);","typeGuard":"const isCallable = (v) => typeof v === 'function';\n\n// usage\nif (isCallable(bootstrap)) appsmith.onReady(bootstrap);","tryCatchPattern":"try {\n  appsmith.onReady(bootstrap);\n} catch (e) {\n  console.error('onReady registration failed:', e.message);\n}","preventionTips":["Pass the function reference; never invoke it at the call site.","Keep the callback idempotent; only the last registered one is retained.","Run bootstrap inside the callback so the host channel is ready.","Lint for appsmith.onReady(\\w+\\(\\)) to catch accidental invocations."],"tags":["custom-widget","wds","appsmith-api","parameter-validation","javascript"],"backgroundTag":null,"analyzedSha":"8cd9021c24cdbea1c3c12c966073708e83db60c2","analyzedAt":"2026-08-12T22:14:19.293Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}