alibaba/canal · error · CanalServerException
invalid destinations expr
Error message
invalid destinations expr
What it means
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.
Source
Thrown at deployer/src/main/java/com/alibaba/otter/canal/deployer/CanalController.java:508
range = StringUtils.substringBefore(range, "}");
String regex = "(\\d+)-(\\d+)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(range);
if (matcher.find()) {
String head = matcher.group(1);
String tail = matcher.group(2);
int start = Integer.parseInt(head);
int end = Integer.parseInt(tail);
List<String> list = new ArrayList<>();
for (int i = start; i <= end; i++) {
String d = prefix + i;
list.add(d);
}
return list.stream().map(Object::toString).collect(Collectors.joining(","));
} else {
throw new CanalServerException("invalid destinations expr " + expr);
}
}
public void start() throws Throwable {
logger.info("## start the canal server[{}({}):{}]", ip, registerIp, port);
// 创建整个canal的工作节点
final String path = ZookeeperPathUtils.getCanalClusterNode(registerIp + ":" + port);
initCid(path);
if (zkclientx != null) {
this.zkclientx.subscribeStateChanges(new IZkStateListener() {
public void handleStateChanged(KeeperState state) throws Exception {
}
public void handleNewSession() throws Exception {
initCid(path);
}View on GitHub (pinned to 87be50e876)
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.
Example fix
# before
canal.instance.destinations.expr = topic1,topic2
# after (for a list, use the plain property)
canal.destinations = topic1,topic2
# or (for a range)
canal.instance.destinations.expr = topic{1-2} Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern RANGE = Pattern.compile("^(.*)\\{(\\d+)-(\\d+)\\}$");
boolean isValidDestinationsExpr(String expr) {
return expr != null && RANGE.matcher(expr).matches();
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- can't find destination:
- canal.user = , but canal.passwd is empty , pls check https:
- unknow mode : for monitor
- unknown mode :
- canal.admin.passwd is empty , pls check https://github.com/a
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/f0a2a287f4b9f652.
Report an issue: GitHub.