#9437: fix: normalize accountId in binding matching for consistent routing
stale
Fixes #9351
## Summary
Telegram multi-account/bot routing was inconsistent due to accountId normalization mismatch in binding matching logic.
## Problem
In `resolveAgentRoute()`, the input accountId was normalized using the proper `normalizeAccountId()` from `session-key.ts` (which lowercases and sanitizes), but the binding's accountId was only trimmed using a local function.
This caused bindings to not match when users configured accountId with different casing:
```json
{
"bindings": [
{ "agentId": "main", "match": { "channel": "telegram", "accountId": "Bot1" } },
{ "agentId": "secondary", "match": { "channel": "telegram", "accountId": "Bot2" } }
]
}
```
When bot2 received messages with `accountId: "bot2"` (normalized), the binding with `"Bot2"` wouldn't match because `"Bot2" !== "bot2"`.
## Solution
- Import the proper `normalizeAccountId` from `session-key.ts`
- Remove the local version that only trimmed
- Use consistent normalization for both binding config values and input accountId
## Changes
- `src/routing/resolve-route.ts`: Fixed `matchesAccountId()` to normalize both sides of the comparison
## Testing
After this fix, these binding configurations will all work correctly:
```json
// All these will match an input accountId of "bot2":
{ "accountId": "bot2" } // exact match
{ "accountId": "Bot2" } // case difference - now works
{ "accountId": "BOT2" } // case difference - now works
{ "accountId": "*" } // wildcard - still works
```
## Related
- Related to Feishu fix: #8975
- Similar issues: #9110, #9058, #8692, #8773
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This change updates `src/routing/resolve-route.ts` to use the shared `normalizeAccountId()` implementation from `src/routing/session-key.ts` when comparing binding `match.accountId` values against the normalized input `accountId`, aiming to make routing consistent across casing/sanitization differences (notably for Telegram multi-account/bot bindings).
<h3>Confidence Score: 2/5</h3>
- This PR has a functional regression risk around wildcard accountId matching.
- The change introduces normalization before wildcard handling; because `normalizeAccountId()` sanitizes `*` into the default value, bindings using `accountId: "*"` will no longer match non-default accounts, changing routing behavior.
- src/routing/resolve-route.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#13477: routing: normalize account ID matching for agent bindings
by davidahmann · 2026-02-10
89.5%
#15727: fix(routing): resolve channel default account instead of hardcoded ...
by FuseWeb · 2026-02-13
82.8%
#14359: fix: prefer named Telegram account over orphan 'default' in binding...
by itsGustav · 2026-02-12
79.3%
#8507: fix: preserve accountId for multi-account agent-to-agent messaging
by djh58 · 2026-02-04
79.1%
#8694: Fix Telegram routing when token override omits accountId
by codvik · 2026-02-04
76.5%
#8095: fix(sessions): include accountId in deliveryContext for outbound pe...
by codeslayer44 · 2026-02-03
75.7%
#8357: fix(gateway): preserve accountId across gateway restarts
by alfredo-feat-volky · 2026-02-03
75.7%
#23656: fix(routing): trust binding agentId even when not in agents.list
by SleuthCo · 2026-02-22
74.8%
#19615: fix(discord): include default account when sub-accounts are configured
by prue-starfield · 2026-02-18
74.7%
#14888: fix(routing): normalize peer.kind in matchesPeer for symmetric comp...
by omair445 · 2026-02-12
74.0%