Skip to content

msteams plugin: three stacked bugs prevent inbound Teams webhooks on v2026.3.24 #56603

@bo-blue

Description

@bo-blue

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

After upgrading to v2026.3.24, the msteams plugin is completely non-functional for inbound message delivery. Three separate bugs compound to prevent any Teams webhook from being processed. Each bug masks the one beneath it, making diagnosis extremely difficult.

Environment

  • OpenClaw v2026.3.24
  • macOS (Apple Silicon, Homebrew install)
  • Node 25.6.1
  • Azure Bot Service (S1), Tailscale Funnel as public endpoint
  • Teams channel shows "Healthy" in Azure, messaging endpoint confirmed correct

Bug 1: Express 5 route syntax crash (known — #54960)

Symptom: msteams plugin crash-loops on boot.

Root cause: The Bot Framework adapter uses /api* glob syntax which is invalid in Express 5 (shipped with v2026.3.24). Express 5 requires named wildcards.

Error:

TypeError: Missing parameter name at index 5: /api*
[msteams] [default] auto-restart attempt 6/10 in 163s

Workaround:

python3 -c "
f = '/opt/homebrew/lib/node_modules/openclaw/dist/dist-B5zoW1KK.js'
with open(f, 'r') as fh: content = fh.read()
old = 'this.express.use(\"/api*\", express_1.default.json())'
new = 'this.express.use(\"/api{*path}\", express_1.default.json())'
if old in content:
    with open(f, 'w') as fh: fh.write(content.replace(old, new))
    print('Patched')
"

Note: Already filed as #54960. Including here because it's the first layer that must be fixed before the other two become visible.


Bug 2 (suspected): JWKS endpoint mismatch — JWT validation fails silently

Symptom: After fixing the boot crash, the plugin starts cleanly but inbound Teams webhooks produce zero log entries — no error, no rejection, no message handler invocation.

Suspected root cause: Microsoft's Bot Framework Service may now be signing webhook tokens with Entra ID keys (issuer: login.microsoftonline.com), but the msteams plugin's createServiceTokenValidator may validate only against the legacy Bot Framework JWKS endpoint (login.botframework.com/v1/.well-known/keys). If the signing key ID in the inbound JWT does not exist at the legacy endpoint, validation fails silently with no log output.

Note: We were unable to confirm this directly because no JWT validation errors appeared in our logs — the silence itself may indicate pre-handler rejection, or may be explained by Bug 3 masking it.

Expected behavior: The JWT validator should check both the Entra ID and legacy Bot Framework JWKS endpoints.


Bug 3: dmPolicy "allowlist" silently drops all inbound messages

Symptom: Even with the boot crash fixed and dmPolicy set to allowlist, inbound messages produce zero log entries. Complete silence.

Root cause: The dmPolicy: "allowlist" configuration silently drops all inbound DMs with no logging — same pattern as #25793 and #11011 (Telegram/Matrix). Unlike those channels, the msteams channel has no equivalent logging for rejected or dropped messages, making diagnosis extremely difficult.

Note: dmPolicy: "pairing" (the default) may have a similar issue — stale conversation references from before the plugin migration may cause silent drops. We could not confirm this because Bug 1 was masking it during initial testing.

Comparison: The Telegram channel handles pairing and allowlist policies with appropriate logging at each decision point. The msteams channel has none.


Request

  1. Fix Bug 1 upstream (bump @microsoft/teams.apps to 2.0.6 per [msteams] Channel fails to start on 2026.3.24 — pathToRegexp "Missing parameter name at index 5: /api*" #54852, or patch the wildcard route)
  2. Confirm/investigate Bug 2: does createServiceTokenValidator check both JWKS endpoints?
  3. Fix Bug 3: add logging to the msteams dmPolicy enforcement path — at minimum log when a message is dropped and why
  4. Consider: a openclaw doctor check that validates msteams inbound delivery end-to-end (send a test webhook and verify it reaches the message handler)

Steps to reproduce

  1. Configure msteams channel with valid appId, appPassword, tenantId, Tailscale Funnel as public endpoint
  2. Upgrade to OpenClaw v2026.3.24
  3. Restart gateway
  4. Send a DM to the Bo app in Microsoft Teams
  5. Check gateway logs for any inbound activity

Expected behavior

After applying the Bug 1 workaround: gateway boots clean, msteams plugin starts without crash, Azure shows Teams channel as Healthy. Inbound Teams messages are received by the agent and processed correctly.

Actual behavior

Bug 1: Gateway crash-loops on boot, msteams channel never starts.

After Bug 1 workaround: Gateway starts cleanly, msteams boots on port 3978, Azure Teams channel shows Healthy, Tailscale Funnel responds correctly to test requests (HTTP 401 as expected). However, inbound Teams DMs produce zero log entries — not even a raw channel event. Messages are completely silently dropped. Tried dmPolicy: pairing, allowlist, and open. All produce identical silence. No JWT errors, no routing errors, no message handler invocations.

OpenClaw version

2026.3.24

Operating system

macOS (Apple Silicon, arm64), Homebrew install

Install method

npm (pnpm global install via Homebrew)

Model

anthropic/claude-sonnet-4-6

Provider / routing chain

Anthropic direct

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

Critical — msteams channel is completely non-functional for inbound delivery on v2026.3.24. All three bugs must be fixed for Teams to work. The stacked nature and silent failures make this extremely hard to diagnose without guidance.

Additional information

Related issues: #54960 (Bug 1 — already filed), #54852 (suggests @microsoft/teams.apps 2.0.6 fixes Bug 1), #25793 and #11011 (Bug 3 pattern in Telegram/Matrix).

This is a composite report intended to document all three layers so others upgrading to v2026.3.24 don't spend hours diagnosing each individually.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingregressionBehavior that previously worked and now fails

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions