{"record":{"id":"a0831ae8236241f2","repo":"alibaba/canal","slug":"canal-user-but-canal-passwd-is-empty-pls-ch","errorCode":null,"errorMessage":"canal.user =  , but canal.passwd is empty , pls check https://github.com/alibaba/canal/issues/4941","messagePattern":"canal\\.user =  , but canal\\.passwd is empty , pls check https://github\\.com/alibaba/canal/issues/4941","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"deployer/src/main/java/com/alibaba/otter/canal/deployer/CanalController.java","lineNumber":123,"sourceCode":"            System.setProperty(CanalConstants.CANAL_ALIYUN_SECRETKEY, secretkey);\n        }\n\n        // 准备canal server\n        ip = getProperty(properties, CanalConstants.CANAL_IP);\n        registerIp = getProperty(properties, CanalConstants.CANAL_REGISTER_IP);\n        port = Integer.valueOf(getProperty(properties, CanalConstants.CANAL_PORT, \"11111\"));\n        adminPort = Integer.valueOf(getProperty(properties, CanalConstants.CANAL_ADMIN_PORT, \"11110\"));\n        embeddedCanalServer = CanalServerWithEmbedded.instance();\n        embeddedCanalServer.setCanalInstanceGenerator(instanceGenerator);// 设置自定义的instanceGenerator\n        int metricsPort = Integer.valueOf(getProperty(properties, CanalConstants.CANAL_METRICS_PULL_PORT, \"11112\"));\n        embeddedCanalServer.setMetricsPort(metricsPort);\n\n        this.adminUser = getProperty(properties, CanalConstants.CANAL_ADMIN_USER);\n        this.adminPasswd = getProperty(properties, CanalConstants.CANAL_ADMIN_PASSWD);\n        String user = getProperty(properties, CanalConstants.CANAL_USER);\n        String passwd = getProperty(properties, CanalConstants.CANAL_PASSWD);\n        if (StringUtils.isNotEmpty(user) && StringUtils.isEmpty(passwd)) {\n            throw new IllegalArgumentException(\n                \"canal.user = \" + user + \" , but canal.passwd is empty , pls check https://github.com/alibaba/canal/issues/4941\");\n        }\n        embeddedCanalServer.setUser(user);\n        embeddedCanalServer.setPasswd(passwd);\n\n        String canalWithoutNetty = getProperty(properties, CanalConstants.CANAL_WITHOUT_NETTY);\n        if (canalWithoutNetty == null || \"false\".equals(canalWithoutNetty)) {\n            canalServer = CanalServerWithNetty.instance();\n            canalServer.setIp(ip);\n            canalServer.setPort(port);\n        }\n\n        // 处理下ip为空，默认使用hostIp暴露到zk中\n        if (StringUtils.isEmpty(ip) && StringUtils.isEmpty(registerIp)) {\n            ip = registerIp = AddressUtils.getHostIp();\n        }\n\n        if (StringUtils.isEmpty(ip)) {","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/deployer/src/main/java/com/alibaba/otter/canal/deployer/CanalController.java#L105-L141","documentation":"Thrown during CanalController construction when the canal.user property is non-empty but canal.passwd is empty. This is a startup config-validation guard: a user with no password is almost always a misconfiguration (the password was forgotten or not escaped), not an intentional setup. It points to GitHub issue #4941 which documents the confusing auth failures this combination caused.","triggerScenarios":"canal.properties (or the active properties source) sets canal.user but leaves canal.passwd blank. CanalController reads both via getProperty and checks isNotEmpty(user) && isEmpty(passwd).","commonSituations":"Migrating from anonymous to authenticated Canal clients and forgetting to set the password; a properties file where the password line was commented out; environment-variable override that set user but not passwd.","solutions":["Set canal.passwd in canal.properties to the matching password (or the SCRAM/SHA1 hash if using hashed passwords).","If you intended no authentication, clear canal.user instead so both are empty.","Ensure no environment variable or -D override sets canal.user without also setting canal.passwd.","Restart Canal after correcting the properties."],"exampleFix":"# before (canal.properties)\ncanal.user = canal\n# canal.passwd =\n# after\ncanal.user = canal\ncanal.passwd = yourPasswordOrHash","handlingStrategy":"validation","validationCode":"// Pre-flight config check before constructing CanalController\nString user = properties.getProperty(CanalConstants.CANAL_USER);\nString passwd = properties.getProperty(CanalConstants.CANAL_PASSWD);\nif (StringUtils.isNotEmpty(user) && StringUtils.isEmpty(passwd)) {\n    throw new IllegalArgumentException(\n        \"canal.user is set but canal.passwd is empty; set the password or clear the user.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set canal.user and canal.passwd together, or leave both empty.","Validate canal.properties in CI/deploy scripts before starting Canal.","Watch for env-var overrides that set only one of the pair."],"tags":["config","auth","startup","deployer"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}