maxAttempts. That is the one value that genuinely means routing.
The log names the cause
Each of these is at WARN or ERROR and needs no debug flag turned on.Two things to rule out before editing any rule
Is a vendor bound at all?
Is a vendor bound at all?
A perfect catch-all pointing at a disconnected vendor delivers nothing and looks exactly like a
routing bug.Answers in words: “N vendor(s) configured, none bound — nothing can be sent yet.”
Is a filter missing or disabled?
Is a filter missing or disabled?
A rule referencing one is skipped entirely rather than loaded with fewer conditions — because
dropping conditions would silently widen the rule.Look for
Skipping … filter '…' is missing or disabled. If that emptied the default table, the
whole routing configuration is refused and you are in the ERROR case above.Why a rule did not match
Six causes, and the last two account for most of the surprises:- Rules are evaluated top to bottom; a NORMAL table stops at the first match.
- The fallback must be at the end. A catch-all above other rules makes everything below it unreachable — the panel’s routing page warns about both cases.
- Attribute names must match those in the routing reference.
- String comparisons are case-sensitive unless
equalsIgnoreCaseis used. startsWithcompares literal text. A regular expression written into it can never be true — usematches. The panel warns; a hand-edited file does not.- An unset field matches no positive operator,
isNullexcepted.product:equals:premiumdoes not match a message carrying no product at all — butproduct:!equals:premiumdoes.
Tracing one message
SetoutSms.routing.trace to a single message serial or account id. Every rule that message is
tested against then logs which condition failed and what the message actually held:
The two queue numbers
Related
How routing works
Tables, rules, and the order they resolve in.
Vendor rejections
When the vendor is bound and refusing every submit.