{"record":{"id":"b2a9e732e56086aa","repo":"appsmithorg/appsmith","slug":"onthemechange-expects-a-function-as-parameter","errorCode":null,"errorMessage":"onThemeChange expects a function as parameter","messagePattern":"onThemeChange expects a function as parameter","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/client/src/widgets/CustomWidget/component/customWidgetscript.js","lineNumber":208,"sourceCode":"      window.appsmith.theme = event.theme;\n      // Notify theme subscribers\n      themeSubscribers.forEach((fn) => {\n        fn(event.theme, prevTheme);\n      });\n    }\n  });\n\n  if (!window.appsmith) {\n    // Define appsmith global object\n    Object.defineProperty(window, \"appsmith\", {\n      configurable: false,\n      writable: false,\n      value: {\n        mode: \"\",\n        theme: {},\n        onThemeChange: (fn) => {\n          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          }","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/appsmithorg/appsmith/blob/8cd9021c24cdbea1c3c12c966073708e83db60c2/app/client/src/widgets/CustomWidget/component/customWidgetscript.js#L190-L226","documentation":"Plain Error thrown by the custom-widget runtime's appsmith.onThemeChange(fn) when the argument is not a function. The custom widget exposes a small appsmith global; onThemeChange registers a subscriber that is invoked immediately with the current theme and on every subsequent theme change. A non-function argument cannot be invoked, so registration is rejected before the subscriber is pushed.","triggerScenarios":"Calling appsmith.onThemeChange() with no argument, a string, an object, or undefined; destructuring the API incorrectly and passing the wrong value.","commonSituations":"Copying example code that omits the callback; passing an arrow stored in a serialised config; refactoring that renames the handler out of scope.","solutions":["Pass a function reference: appsmith.onThemeChange((theme) => { ... }).","Capture the returned unsubscribe function and call it on cleanup to avoid leaks.","If invoking conditionally, guard with typeof fn === 'function' before registering."],"exampleFix":"// before\nappsmith.onThemeChange('dark');\n// after\nappsmith.onThemeChange((theme) => console.log(theme));","handlingStrategy":"type-guard","validationCode":"if (typeof handler !== 'function') {\n  console.warn('onThemeChange: expected a function');\n  return;\n}\nconst unsubscribe = appsmith.onThemeChange(handler);","typeGuard":"function isListener(v: unknown): v is Function {\n  return typeof v === 'function';\n}","tryCatchPattern":null,"preventionTips":["Always pass a function reference; never the result of calling it.","Capture the unsubscribe return value and call it on widget teardown.","Keep custom-widget boilerplate copy-paste consistent."],"tags":["custom-widget","theme","validation","runtime"],"backgroundTag":null,"analyzedSha":"8cd9021c24cdbea1c3c12c966073708e83db60c2","analyzedAt":"2026-08-12T22:14:19.293Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}