{"record":{"id":"f0a2a287f4b9f652","repo":"alibaba/canal","slug":"invalid-destinations-expr","errorCode":null,"errorMessage":"invalid destinations expr ","messagePattern":"invalid destinations expr ","errorType":"exception","errorClass":"CanalServerException","httpStatus":null,"severity":"error","filePath":"deployer/src/main/java/com/alibaba/otter/canal/deployer/CanalController.java","lineNumber":508,"sourceCode":"        range = StringUtils.substringBefore(range, \"}\");\n\n        String regex = \"(\\\\d+)-(\\\\d+)\";\n        Pattern pattern = Pattern.compile(regex);\n        Matcher matcher = pattern.matcher(range);\n        if (matcher.find()) {\n            String head = matcher.group(1);\n            String tail = matcher.group(2);\n            int start = Integer.parseInt(head);\n            int end = Integer.parseInt(tail);\n\n            List<String> list = new ArrayList<>();\n            for (int i = start; i <= end; i++) {\n                String d = prefix + i;\n                list.add(d);\n            }\n            return list.stream().map(Object::toString).collect(Collectors.joining(\",\"));\n        } else {\n            throw new CanalServerException(\"invalid destinations expr \" + expr);\n        }\n    }\n\n    public void start() throws Throwable {\n        logger.info(\"## start the canal server[{}({}):{}]\", ip, registerIp, port);\n        // 创建整个canal的工作节点\n        final String path = ZookeeperPathUtils.getCanalClusterNode(registerIp + \":\" + port);\n        initCid(path);\n        if (zkclientx != null) {\n            this.zkclientx.subscribeStateChanges(new IZkStateListener() {\n\n                public void handleStateChanged(KeeperState state) throws Exception {\n\n                }\n\n                public void handleNewSession() throws Exception {\n                    initCid(path);\n                }","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/deployer/src/main/java/com/alibaba/otter/canal/deployer/CanalController.java#L490-L526","documentation":"Thrown by CanalController.parseExpr when a destinations expression (canal.instance.destinations.expr) does not match the expected 'prefix{start-end}' pattern. The method splits on '{' and '}', then applies regex (\\d+)-(\\d+) to the inner range. If the braces are missing, the range isn't two hyphen-separated integers, or the format is otherwise malformed, it throws CanalServerException.","triggerScenarios":"Setting canal.instance.destinations.expr to a value without the {N-M} range syntax, e.g. 'topic1,topic2' (use canal.destinations for a plain list), or 'topic{1-100' (missing closing brace), or 'topic{a-b}' (non-numeric).","commonSituations":"Confusing the expression syntax (range expansion) with the plain comma-separated canal.destinations list; missing or misplaced braces; using characters instead of integers in the range.","solutions":["Use the exact format prefix{start-end}, e.g. canal.instance.destinations.expr = topic{1-100}.","For a plain comma-separated list, use canal.destinations instead of the expr property.","Ensure start and end are integers and start <= end.","Do not nest additional characters inside the braces."],"exampleFix":"# before\ncanal.instance.destinations.expr = topic1,topic2\n# after (for a list, use the plain property)\ncanal.destinations = topic1,topic2\n# or (for a range)\ncanal.instance.destinations.expr = topic{1-2}","handlingStrategy":"validation","validationCode":"private static final Pattern RANGE = Pattern.compile(\"^(.*)\\\\{(\\\\d+)-(\\\\d+)\\\\}$\");\nboolean isValidDestinationsExpr(String expr) {\n    return expr != null && RANGE.matcher(expr).matches();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the exact prefix{start-end} syntax for range expressions.","For plain comma-separated lists, use canal.destinations, not the expr property.","Validate the expression in deploy scripts before starting Canal."],"tags":["config","destination","startup","deployer"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}