{"record":{"id":"3596fd4b611f7e56","repo":"alibaba/canal","slug":"init-alarmhandlerplugindir-s-alarm-handler-s","errorCode":null,"errorMessage":"init alarmHandlerPluginDir [%s] alarm handler [%s] error: %s","messagePattern":"init alarmHandlerPluginDir \\[(.+?)\\] alarm handler \\[(.+?)\\] error: (.+?)","errorType":"exception","errorClass":"CanalException","httpStatus":null,"severity":"error","filePath":"instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/CanalInstanceWithManager.java","lineNumber":129,"sourceCode":"                    throw new IllegalStateException(String.format(\"alarmHandlerPluginDir [%s] can't find any name endswith \\\".jar\\\" file.\",\n                        alarmHandlerPluginDir));\n                }\n                URL[] urls = new URL[jarFiles.length];\n                for (int i = 0; i < jarFiles.length; i++) {\n                    urls[i] = jarFiles[i].toURI().toURL();\n                }\n                ClassLoader currentClassLoader = new URLClassLoader(urls,\n                    CanalInstanceWithManager.class.getClassLoader());\n                Class<CanalAlarmHandler> _alarmClass = (Class<CanalAlarmHandler>) currentClassLoader.loadClass(alarmHandlerClass);\n                alarmHandler = _alarmClass.newInstance();\n                logger.info(\"init [{}] alarm handler success.\", alarmHandlerClass);\n            } catch (Throwable e) {\n                String errorMsg = String.format(\"init alarmHandlerPluginDir [%s] alarm handler [%s] error: %s\",\n                    alarmHandlerPluginDir,\n                    alarmHandlerClass,\n                    ExceptionUtils.getFullStackTrace(e));\n                logger.error(errorMsg);\n                throw new CanalException(errorMsg, e);\n            }\n        }\n        logger.info(\"init alarmHandler end! \\n\\t load CanalAlarmHandler:{} \", alarmHandler.getClass().getName());\n    }\n\n    protected void initMetaManager() {\n        logger.info(\"init metaManager begin...\");\n        MetaMode mode = parameters.getMetaMode();\n        if (mode.isMemory()) {\n            metaManager = new MemoryMetaManager();\n        } else if (mode.isZookeeper()) {\n            metaManager = new ZooKeeperMetaManager();\n            ((ZooKeeperMetaManager) metaManager).setZkClientx(getZkclientx());\n        } else if (mode.isMixed()) {\n            // metaManager = new MixedMetaManager();\n            metaManager = new PeriodMixedMetaManager();// 换用优化过的mixed, at\n                                                       // 2012-09-11\n            // 设置内嵌的zk metaManager","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/CanalInstanceWithManager.java#L111-L147","documentation":"The catch-all in initAlarmHandler() (CanalInstanceWithManager.java:123-130): any Throwable raised while building the URLClassLoader from the plugin jars, loading canal.alarm.handler.class, or instantiating it via newInstance() is wrapped into a CanalException whose message embeds the full stack trace (ExceptionUtils.getFullStackTrace). Common inner causes: ClassNotFoundException (class name typo / not present in any jar), NoClassDefFoundError/LinkageError (dependency mismatch), InstantiationException/IllegalAccessException (no public no-arg constructor or class is abstract), or the IllegalStateException from error 344.","triggerScenarios":"Configuring alarmHandlerClass + alarmHandlerPluginDir and starting the instance when loadClass or newInstance fails for any reason — wrong class FQN, class not in any listed jar, missing transitive dependency, non-public/no no-arg constructor, security manager blocking access, or the plugin dir containing no jars (error 344 propagates here).","commonSituations":"Custom alarm handler jar built against a different canal version (binary incompatibility → LinkageError); class name in config doesn't match the packaged class; plugin shaded/relocated so the FQN changed; alarm handler depends on a library not shipped in the plugin dir or canal lib dir; constructor removed or made private during a refactor.","solutions":["Read the embedded stack trace in the CanalException message — it names the root cause class (ClassNotFoundException / NoClassDefFoundError / InstantiationException).","If ClassNotFoundException/NoClassDefFoundError: confirm the class FQN exactly matches canal.alarm.handler.class and that the class is present in one of the jars in the plugin dir (jar tf <jar> | grep <class>).","If InstantiationException/IllegalAccessException: ensure the alarm handler class is public, concrete, and has a public no-arg constructor.","If LinkageError/IncompatibleClassChangeError: rebuild the plugin against the canal version actually deployed, and verify transitive deps do not conflict with canal's own lib/.","If the cause is the IllegalStateException from error 344 (no jars found), fix the plugin dir first."],"exampleFix":"// before — alarm handler with no public no-arg ctor\npublic class MyAlarmHandler implements CanalAlarmHandler {\n    private final Notifier notifier;\n    public MyAlarmHandler(Notifier n) { this.notifier = n; }\n    // ...\n}\n\n// after — canal calls newInstance(), needs a public no-arg ctor\npublic class MyAlarmHandler implements CanalAlarmHandler {\n    public MyAlarmHandler() { this(new DefaultNotifier()); }\n    // ...\n}","handlingStrategy":"try-catch","validationCode":"// Validate the alarm handler class is loadable from the plugin dir before starting the instance\nFile dir = new File(parameters.getAlarmHandlerPluginDir());\nURL[] urls = Arrays.stream(dir.listFiles((f, n) -> n.endsWith(\".jar\")))\n    .map(f -> { try { return f.toURI().toURL(); } catch (Exception e) { throw new RuntimeException(e); } })\n    .toArray(URL[]::new);\ntry (URLClassLoader cl = new URLClassLoader(urls, CanalInstanceWithManager.class.getClassLoader())) {\n    Class<?> c = cl.loadClass(parameters.getAlarmHandlerClass());\n    int mods = c.getModifiers();\n    if (!Modifier.isPublic(mods) || Modifier.isAbstract(mods)\n        || c.getDeclaredConstructor() == null || !Modifier.isPublic(c.getDeclaredConstructor().getModifiers())) {\n        throw new IllegalStateException(\"alarm handler class must be public, concrete, with a public no-arg ctor\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    instance.start();\n} catch (CanalException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"init alarmHandlerPluginDir\")) {\n        // message embeds the full stack trace; inspect for ClassNotFoundException/LinkageError\n        log.error(\"alarm handler init failed; check class FQN, jar contents, canal version compatibility\");\n    }\n    throw e;\n}","preventionTips":["Build custom alarm-handler jars against the exact canal version deployed to avoid LinkageError.","Confirm the class FQN exists in one of the plugin jars (jar tf | grep).","Keep a public no-arg constructor on the alarm handler class.","Ship all transitive plugin dependencies in the plugin dir or canal lib/."],"tags":["configuration","plugin","alarm-handler","classloader","instance-manager","initialization"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}