apache/dubbo · error · IllegalArgumentException

Illegal route rule!

Error message

Illegal route rule!

What it means

Thrown by MultiDestConditionRouter.init() when either the 'from' or 'to' condition map is null. This router is built from a MultiDestCondition (multi-destination routing with weighted subsets); both a source (from) and at least one destination (to) must be supplied.

Source

Thrown at dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/MultiDestConditionRouter.java:75

    private Map<String, ConditionMatcher> whenCondition;
    private List<ConditionSubSet> thenCondition;
    private boolean force;
    protected List<ConditionMatcherFactory> matcherFactories;
    private boolean enabled;

    public MultiDestConditionRouter(URL url, MultiDestCondition multiDestCondition, boolean force, boolean enabled) {
        super(url);
        this.setForce(force);
        this.enabled = enabled;
        matcherFactories =
                moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions();
        this.init(multiDestCondition.getFrom(), multiDestCondition.getTo());
    }

    public void init(Map<String, String> from, List<Map<String, String>> to) {
        try {
            if (from == null || to == null) {
                throw new IllegalArgumentException("Illegal route rule!");
            }
            String whenRule = from.get("match");
            Map<String, ConditionMatcher> when =
                    StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<>() : parseRule(whenRule);
            this.whenCondition = when;

            List<ConditionSubSet> thenConditions = new ArrayList<>();
            for (Map<String, String> toMap : to) {
                String thenRule = toMap.get("match");
                Map<String, ConditionMatcher> then = StringUtils.isBlank(thenRule) || "false".equals(thenRule)
                        ? new HashMap<>()
                        : parseRule(thenRule);
                // NOTE: It should be determined on the business level whether the `When condition` can be empty or not.

                thenConditions.add(new ConditionSubSet(
                        then,
                        Integer.valueOf(
                                toMap.getOrDefault("weight", String.valueOf(DefaultRouteConditionSubSetWeight)))));

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Provide both a non-null 'from' map and a non-null 'to' list in the MultiDestCondition.
  2. Validate the route definition completeness before registering the router; both source and destination(s) are mandatory.
  3. Check the upstream config (mesh/virtual-service or app routing) serialization for missing fields.

Example fix

// before: to == null -> throws
new MultiDestConditionRouter(url, new MultiDestCondition(fromMap, null), false, true);

// after: supply non-null from and to
List<Map<String,String>> toList = List.of(Map.of("match", "provider.region=east", "weight", "80"));
new MultiDestConditionRouter(url, new MultiDestCondition(fromMap, toList), false, true);
Defensive patterns

Strategy: validation

Validate before calling

// Validate MultiDestCondition before constructing the router
if (multiDestCondition.getFrom() == null || multiDestCondition.getTo() == null) {
    throw new IllegalArgumentException(
        "MultiDest route requires non-null 'from' and 'to'; got from="
            + multiDestCondition.getFrom() + ", to=" + multiDestCondition.getTo());
}
return new MultiDestConditionRouter<>(url, multiDestCondition, force, enabled);

Try / catch

try {
    new MultiDestConditionRouter<>(url, cond, force, enabled);
} catch (IllegalArgumentException | IllegalStateException e) {
    log.error("MultiDestConditionRouter init failed (from/to missing): " + e.getMessage());
    // skip this router in the chain
}

Prevention

When it happens

Trigger: Constructing MultiDestConditionRouter with a MultiDestCondition whose getFrom() or getTo() returns null — i.e., a multi-destination route definition missing the from-block or the to-block list.

Common situations: Defining a multi-destination / weighted-subset route rule (typically from mesh-style or app-level routing config) and omitting the 'from' match or the 'to' destinations; malformed YAML/JSON deserializing a missing block to null.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/89aa97073e47a9dc. Report an issue: GitHub.