{"record":{"id":"179db3f0fd0c3cc2","repo":"appsmithorg/appsmith","slug":"onuichange-expects-a-function-as-parameter","errorCode":null,"errorMessage":"onUiChange expects a function as parameter","messagePattern":"onUiChange expects a function as parameter","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/client/src/widgets/CustomWidget/component/customWidgetscript.js","lineNumber":225,"sourceCode":"          if (typeof fn !== \"function\") {\n            throw new Error(\"onThemeChange expects a function as parameter\");\n          }\n\n          themeSubscribers.push(fn);\n          fn(window.appsmith.theme);\n\n          return () => {\n            // Unsubscribe from theme changes\n            const index = themeSubscribers.indexOf(fn);\n\n            if (index > -1) {\n              themeSubscribers.splice(index, 1);\n            }\n          };\n        },\n        onUiChange: (fn) => {\n          if (typeof fn !== \"function\") {\n            throw new Error(\"onUiChange expects a function as parameter\");\n          }\n\n          uiSubscribers.push(fn);\n          fn(window.appsmith.ui);\n\n          return () => {\n            // Unsubscribe from UI changes\n            const index = uiSubscribers.indexOf(fn);\n\n            if (index > -1) {\n              uiSubscribers.splice(index, 1);\n            }\n          };\n        },\n        onModelChange: (fn) => {\n          if (typeof fn !== \"function\") {\n            throw new Error(\"onModelChange expects a function as parameter\");\n          }","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/appsmithorg/appsmith/blob/8cd9021c24cdbea1c3c12c966073708e83db60c2/app/client/src/widgets/CustomWidget/component/customWidgetscript.js#L207-L243","documentation":"Plain Error thrown by the custom-widget runtime's appsmith.onUiChange(fn) when the argument is not a function. onUiChange registers a subscriber invoked immediately with the current ui model and whenever the UI changes from outside the widget. A non-function argument would be un-callable, so registration is rejected and no subscriber is added.","triggerScenarios":"Calling appsmith.onUiChange() with no argument, a string, a number, an object, or undefined; passing the result of a function call instead of the function reference.","commonSituations":"Boilerplate left half-edited; passing a model object instead of a listener; refactoring broke the handler reference.","solutions":["Pass a function reference: appsmith.onUiChange((ui) => { ... }).","Store the returned unsubscribe function and call it in your widget cleanup.","Guard with typeof fn === 'function' if you conditionally subscribe."],"exampleFix":"// before\nappsmith.onUiChange(uiModel);\n// after\nappsmith.onUiChange((ui) => render(ui));","handlingStrategy":"type-guard","validationCode":"if (typeof handler !== 'function') {\n  console.warn('onUiChange: expected a function');\n  return;\n}\nconst unsubscribe = appsmith.onUiChange(handler);","typeGuard":"function isListener(v: unknown): v is Function {\n  return typeof v === 'function';\n}","tryCatchPattern":null,"preventionTips":["Pass the listener function, not a model object.","Call the returned unsubscribe on cleanup to prevent leaks.","Validate with typeof before subscribing when wiring dynamically."],"tags":["custom-widget","ui","validation","runtime"],"backgroundTag":null,"analyzedSha":"8cd9021c24cdbea1c3c12c966073708e83db60c2","analyzedAt":"2026-08-12T22:14:19.293Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}