Skip to content

fix(msteams): prevent path-to-regexp crash with express 5 (#55161)#55440

Merged
BradGroux merged 1 commit intoopenclaw:mainfrom
lml2468:bgod/55161-teams-path-to-regexp
Apr 1, 2026
Merged

fix(msteams): prevent path-to-regexp crash with express 5 (#55161)#55440
BradGroux merged 1 commit intoopenclaw:mainfrom
lml2468:bgod/55161-teams-path-to-regexp

Conversation

@lml2468
Copy link
Copy Markdown
Contributor

@lml2468 lml2468 commented Mar 27, 2026

Problem

The MS Teams channel crashes immediately on startup in 2026.3.24 with:

Missing parameter name at index 5: /api*

Fixes #55161

Root Cause

The Teams SDK (@microsoft/teams.apps@2.0.5) has a built-in HttpPlugin that registers an Express middleware with the pattern /api* in its constructor. This pattern was valid in Express 4, but is invalid in Express 5 which uses path-to-regexp@8.x.

When installed in OpenClaw's monorepo, pnpm hoisting resolves the SDK's express import to the project's top-level express@5.2.1 instead of Express 4, causing the crash.

Fix

Inject a no-op HTTP plugin stub into the Teams SDK's App constructor to prevent the default HttpPlugin from being created. OpenClaw manages its own Express routing, so the SDK's built-in HTTP handling is not needed.

Testing

  • 2/2 unit tests pass including a new regression test that verifies the fix using the real Teams SDK + express 5
  • 4 pre-existing failures in attachments.test.ts are SSRF/DNS environment issues unrelated to this change (confirmed on main branch too)

@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: S labels Mar 27, 2026
@lml2468 lml2468 force-pushed the bgod/55161-teams-path-to-regexp branch from 72beea0 to faa2461 Compare March 27, 2026 01:14
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 27, 2026

Greptile Summary

This PR fixes a startup crash in the MS Teams channel (Missing parameter name at index 5: /api*) caused by @microsoft/teams.apps's built-in HttpPlugin registering an Express 4 route pattern that is rejected by Express 5's path-to-regexp@8.x.\n\nThe fix injects a no-op HTTP plugin stub into the Teams SDK App constructor, preventing the default HttpPlugin from being created at all. Since OpenClaw manages its own Express routing for the Teams webhook, the SDK's built-in HTTP handling is genuinely not needed.\n\nKey changes:\n- New createNoOpHttpPlugin() uses reflect-metadata to tag a minimal stub class with the SDK's plugin registry key \"http\", so the App treats it as an already-registered HTTP plugin and skips the default one.\n- createMSTeamsApp is promoted from synchronous to async to accommodate the lazy imports inside createNoOpHttpPlugin; the single downstream caller (loadMSTeamsSdkWithAuth) is updated accordingly.\n- A new regression test exercises the real SDK + Express 5 combination to verify the crash is gone.\n\nOne concern to watch: createNoOpHttpPlugin reaches into three private dist/ paths of @microsoft/teams.apps to obtain reflect-metadata key constants. While correct for @microsoft/teams.apps@2.0.5, these paths are not part of the SDK's public API and could break on any future SDK update. Hardcoding or snapshotting the actual string values would make the fix more durable.

Confidence Score: 4/5

Safe to merge — fixes a real startup crash with a targeted workaround and a passing regression test; the only risk is future SDK updates breaking the internal dist/ imports.

The root cause is well-understood, the fix is minimal and correctly scoped, and the regression test uses the real SDK against Express 5. One non-blocking fragility remains (deep private imports from the SDK's dist/ tree), but it does not affect current correctness.

extensions/msteams/src/sdk.ts lines 77–82 — the three internal @microsoft/teams.apps/dist/… imports.

Important Files Changed

Filename Overview
extensions/msteams/src/sdk.ts Adds async createNoOpHttpPlugin that stubs the SDK's default HttpPlugin (which uses an Express 5-incompatible route pattern), and threads the stub through createMSTeamsApp and loadMSTeamsSdkWithAuth. Fix is logically sound and well-commented; main fragility is the three deep dist/ imports used to obtain reflect-metadata keys.
extensions/msteams/src/sdk.test.ts Adds a regression test that instantiates the real Teams SDK against Express 5, confirming the startup crash no longer occurs. Existing adapter test is unchanged.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/msteams/src/sdk.ts
Line: 77-82

Comment:
**Fragile deep-private SDK imports**

These three import paths reach directly into the SDK's compiled `dist/` tree rather than its public API surface:

```
@microsoft/teams.apps/dist/types/plugin/decorators/plugin.js
@microsoft/teams.apps/dist/types/plugin/decorators/dependency.js
@microsoft/teams.apps/dist/types/plugin/decorators/event.js
```

Any internal refactor inside `@microsoft/teams.apps` — even a patch release — will silently break MS Teams channel startup, likely with an opaque `MODULE_NOT_FOUND` error rather than a clear message.

Consider whether the three metadata keys could instead be hard-coded as local string constants (snapshotted from the current SDK source), removing the runtime dependency on these internal paths entirely. The values are unlikely to collide with other plugin registry entries, and a snapshot is more stable than a live import of a private file.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(msteams): prevent path-to-regexp cra..." | Re-trigger Greptile

Comment on lines +77 to +82
// FRAGILE: these are internal SDK paths (not public API). If
// @microsoft/teams.apps changes its dist layout, these imports will break.
// Pin the SDK version and re-verify after any upgrade.
await import("reflect-metadata");
const { PLUGIN_METADATA_KEY } =
await import("@microsoft/teams.apps/dist/types/plugin/decorators/plugin.js");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Fragile deep-private SDK imports

These three import paths reach directly into the SDK's compiled dist/ tree rather than its public API surface:

@microsoft/teams.apps/dist/types/plugin/decorators/plugin.js
@microsoft/teams.apps/dist/types/plugin/decorators/dependency.js
@microsoft/teams.apps/dist/types/plugin/decorators/event.js

Any internal refactor inside @microsoft/teams.apps — even a patch release — will silently break MS Teams channel startup, likely with an opaque MODULE_NOT_FOUND error rather than a clear message.

Consider whether the three metadata keys could instead be hard-coded as local string constants (snapshotted from the current SDK source), removing the runtime dependency on these internal paths entirely. The values are unlikely to collide with other plugin registry entries, and a snapshot is more stable than a live import of a private file.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/sdk.ts
Line: 77-82

Comment:
**Fragile deep-private SDK imports**

These three import paths reach directly into the SDK's compiled `dist/` tree rather than its public API surface:

```
@microsoft/teams.apps/dist/types/plugin/decorators/plugin.js
@microsoft/teams.apps/dist/types/plugin/decorators/dependency.js
@microsoft/teams.apps/dist/types/plugin/decorators/event.js
```

Any internal refactor inside `@microsoft/teams.apps` — even a patch release — will silently break MS Teams channel startup, likely with an opaque `MODULE_NOT_FOUND` error rather than a clear message.

Consider whether the three metadata keys could instead be hard-coded as local string constants (snapshotted from the current SDK source), removing the runtime dependency on these internal paths entirely. The values are unlikely to collide with other plugin registry entries, and a snapshot is more stable than a live import of a private file.

How can I resolve this? If you propose a fix, please make it concise.

@BradGroux BradGroux force-pushed the bgod/55161-teams-path-to-regexp branch from faa2461 to e9be2a1 Compare April 1, 2026 14:52
…5161)

The Teams SDK (@microsoft/teams.apps) default HttpPlugin registers an
Express middleware with the pattern `/api*`. When the host application
uses Express 5 (which depends on path-to-regexp v8+), that pattern is
invalid and throws:

  Missing parameter name at index 5: /api*

OpenClaw manages its own Express server for the Teams webhook endpoint
and does not use the SDK's built-in HTTP server. This commit injects a
no-op HTTP plugin stub into the Teams SDK App constructor to prevent
the default HttpPlugin from being created, avoiding the crash entirely.

Changes:
- sdk.ts: Add createNoOpHttpPlugin() that creates a properly decorated
  stub plugin named 'http', and pass it to App constructor
- sdk.ts: Make createMSTeamsApp async (was sync) to support lazy import
  of reflect-metadata and decorator constants
- sdk.test.ts: Add regression test verifying App creation succeeds with
  the real Teams SDK under express 5

Closes openclaw#55161
@BradGroux BradGroux force-pushed the bgod/55161-teams-path-to-regexp branch from e9be2a1 to 84efae9 Compare April 1, 2026 14:59
@BradGroux BradGroux merged commit d555449 into openclaw:main Apr 1, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MS Teams channel crash-loop in 2026.3.24: Missing parameter name at index 5: /api*

3 participants