Skip to content

[Bug]: [msteams] startAccount resolves immediately causing restart loop and EADDRINUSE crash #24374

@virtuetechrocklin

Description

@virtuetechrocklin

Summary

Repo: https://github.com/openclaw/openclaw/issues/new
Title:[msteams] startAccount resolves immediately causing restart loop and EADDRINUSE crash
Body:
Summary
The @openclaw/msteams channel plugin crashes in a restart loop on every gateway start. Each attempt logs msteams server error and is retried with exponential backoff (up to 10 times), making the Teams connector permanently unavailable.
Environment
OpenClaw: 2026.2.22-2 (also present in 2026.2.19-2)
@openclaw/msteams: 2026.2.22
macOS 15.3 (arm64), Node 22.22.0
Microsoft Teams Bot Framework webhook on port 3978
Symptoms
Gateway log repeats indefinitely:
INFO starting provider (port 3978)
INFO msteams provider started on port 3978
INFO [default] auto-restart attempt 1/10 in 5s
INFO [default] auto-restart attempt 2/10 in 11s
ERROR msteams server error ← EADDRINUSE on second+ attempt
INFO [default] auto-restart attempt 3/10 in 22s
...
Root Cause
monitorMSTeamsProvider() in src/monitor.ts calls expressApp.listen(port, callback) and then immediately return { app: expressApp, shutdown } — it does not wait for the server lifecycle to end.
The channel orchestrator's contract (from plugin-sdk type definitions) is:
startAccount?: (ctx) => Promise
The Promise is expected to stay pending while the account is running, and only settle when it stops. When startAccount resolves immediately, the orchestrator treats the account as "exited" and schedules a restart. The new restart tries to bind port 3978 while the old Express server is still draining → EADDRINUSE → msteams server error.
Fix
Wrap the server in a long-lived Promise in src/monitor.ts:
return new Promise((resolve, reject) => {
const httpServer = expressApp.listen(port, () => {
log.info(msteams provider started on port ${port});
});
const shutdown = async () => {
log.info("shutting down msteams provider");
return new Promise((res) => {
httpServer.close((err) => {
if (err) log.debug?.("msteams server close error", { error: String(err) });
res();
});
});
};
httpServer.on("error", (err) => {
log.error("msteams server error", { error: String(err) });
reject(err);
});
httpServer.on("close", () => {
resolve({ app: expressApp, shutdown });
});
if (opts.abortSignal) {
opts.abortSignal.addEventListener("abort", () => {
void shutdown();
});
}
});

This fix has been applied locally and confirmed stable — no more restart loops, Teams connector holds port 3978 cleanly.
Additional Notes
Incoming messages still work even during the crash loop (the webhook receives fine); only auto-routing of replies is broken
The Cannot perform 'set/get' on a proxy that has been revoked errors seen separately are a consequence of this same issue — reply context expires before the retried server stabilizes

Steps to reproduce

  1. Configure a valid msteams channel in openclaw.json (appId, appPassword, tenantId)
  2. Start the OpenClaw gateway (openclaw gateway)
  3. Observe the gateway logs

Expected behavior

Expected: msteams provider starts once and stays running on port 3978

Actual behavior

Actual: Provider starts, then immediately restarts in a loop:

  • "msteams provider started on port 3978"
  • "[default] auto-restart attempt 1/10 in 5s"
  • "[default] auto-restart attempt 2/10 in 11s"
  • "msteams server error" (EADDRINUSE on second+ attempt)
  • Repeats until giving up after 10 attempts

OpenClaw version

2026.2.22-2

Operating system

Macos 26.3

Install method

npm install -g openclaw

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    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