appsmithorg/appsmith · error · Error

onReady expects a function as parameter

Error message

onReady expects a function as parameter

What it means

Thrown by window.appsmith.onReady() in a legacy Custom Widget iframe. onReady registers a single callback that fires once the Appsmith host signals readiness; if the host is already ready and onReady has not been called yet, the callback is invoked synchronously. A non-function argument is rejected because the method immediately assigns onReady = fn and may call it.

Source

Thrown at app/client/src/widgets/CustomWidget/component/customWidgetscript.js:287

        },
        triggerEvent: (eventName, contextObj) => {
          if (typeof eventName !== "string") {
            throw new Error("eventName should be a string");
          } else if (contextObj && typeof contextObj !== "object") {
            throw new Error("contextObj should be an object");
          }

          // Send a trigger event message to the parent
          channel.postMessage(EVENTS.CUSTOM_WIDGET_TRIGGER_EVENT, {
            eventName,
            contextObj,
          });
        },
        model: {},
        ui: {},
        onReady: (fn) => {
          if (typeof fn !== "function") {
            throw new Error("onReady expects a function as parameter");
          }

          onReady = fn;

          if (isReady && !isReadyCalled && onReady) {
            onReady();
            isReadyCalled = true;
          }
        },
      },
    });
  }

  // Listen for the 'load' event and send READY message to the parent
  window.addEventListener("load", () => {
    channel.postMessage(EVENTS.CUSTOM_WIDGET_READY);
  });
}

View on GitHub (pinned to 8cd9021c24)

Solutions

  1. Pass the function reference: appsmith.onReady(init).
  2. Use an inline arrow: appsmith.onReady(() => { /* bootstrap */ }).
  3. Keep onReady idempotent and lightweight since only the last registered callback is retained.
  4. Perform side-effecting bootstrap inside the callback, not at module top-level, to ensure the host channel is ready.

Example fix

// before
appsmith.onReady(bootstrap()); // runs bootstrap, passes undefined

// after
appsmith.onReady(bootstrap); // passes the function reference
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof onReadyHandler !== 'function') {
  throw new TypeError('onReady expects a function');
}
appsmith.onReady(onReadyHandler);

Type guard

const isCallable = (v) => typeof v === 'function';

// usage
if (isCallable(bootstrap)) appsmith.onReady(bootstrap);

Try / catch

try {
  appsmith.onReady(bootstrap);
} catch (e) {
  console.error('onReady registration failed:', e.message);
}

Prevention

When it happens

Trigger: Calling appsmith.onReady(undefined), appsmith.onReady(null), appsmith.onReady('init'), appsmith.onReady({init:fn}), or appsmith.onReady() with no argument. Calling onReady twice with the second arg accidentally omitted.

Common situations: Invoking an init function instead of passing it (onReady(init())); passing a config object that contains the handler; migrating from a Promise-based API and passing onReady(resolve).

Related errors


AI-assisted analysis of appsmithorg/appsmith@8cd9021c24 (2026-08-12). Data as JSON: /api/errors/a76401fa0efa863a. Report an issue: GitHub.