-
-
Notifications
You must be signed in to change notification settings - Fork 52.6k
Description
Bug: FileConsent invoke response sent after file upload causes "Something went wrong" in Teams
Component: @openclaw/msteams plugin
File: extensions/msteams/src/monitor-handler.ts
Severity: Low (functional — file uploads succeed, but UX is degraded)
Summary
When a bot sends a file via FileConsentCard in a personal (DM) chat, the user clicks "Allow", and Teams shows "Something went wrong. Please try again." — even though the file upload succeeds and the file card renders correctly afterward.
Root Cause
The invokeResponse (HTTP 200 acknowledgement) is sent after the file upload and FileInfoCard send (line 133 of monitor-handler.ts), rather than before. This causes Teams to time out waiting for the invoke acknowledgement.
Current flow (broken):
1. Receive invoke (fileConsent/invoke, action: "accept")
2. Parse consent response
3. Get pending upload buffer from store
4. Upload file to OneDrive URL (uploadToConsentUrl) ← SLOW (network I/O)
5. Send FileInfoCard via context.sendActivity() ← SLOW (network I/O)
6. Return true from handleFileConsentInvoke()
7. Send invokeResponse { status: 200 } ← TOO LATE
Expected flow (per Microsoft docs):
1. Receive invoke (fileConsent/invoke, action: "accept")
2. IMMEDIATELY send invokeResponse { status: 200 } ← ACKNOWLEDGE FIRST
3. Upload file to OneDrive URL (async)
4. Send FileInfoCard via context.sendActivity() (async)
Relevant Code
monitor-handler.ts lines 125-135:
handler.run = async (context: unknown) => {
const ctx = context as MSTeamsTurnContext;
if (ctx.activity?.type === "invoke" && ctx.activity?.name === "fileConsent/invoke") {
const handled = await handleFileConsentInvoke(ctx, deps.log); // ← blocks on upload
if (handled) {
await ctx.sendActivity({ type: "invokeResponse", value: { status: 200 } }); // ← too late
return;
}
}
return originalRun.call(handler, context);
};handleFileConsentInvoke() awaits both uploadToConsentUrl() (line 82) and context.sendActivity() for the FileInfoCard (line 94) before returning, delaying the invokeResponse.
Suggested Fix
Move the invokeResponse to fire before the upload:
handler.run = async (context: unknown) => {
const ctx = context as MSTeamsTurnContext;
if (ctx.activity?.type === "invoke" && ctx.activity?.name === "fileConsent/invoke") {
// Acknowledge the invoke IMMEDIATELY
await ctx.sendActivity({ type: "invokeResponse", value: { status: 200 } });
// Then handle the upload asynchronously
handleFileConsentInvoke(ctx, deps.log).catch((err) => {
deps.log.debug?.("file consent handler error", { error: String(err) });
});
return;
}
return originalRun.call(handler, context);
};Secondary Concern
The invokeResponse is sent via sendActivity({ type: "invokeResponse", ... }). Depending on the adapter implementation, this may not correctly map to the HTTP response that Bot Framework expects for invoke acknowledgements. Some adapters require the invoke response to be set on the turn state or returned as the HTTP response body directly.
Reproduction Steps
- Send a file (e.g., PDF) from the bot to a user in a DM
- Bot sends FileConsentCard ("Bot needs permission to upload...")
- User clicks "Allow"
- Observed: "Something went wrong. Please try again." error banner appears
- After a moment, the file card renders correctly with preview and download link
Impact
- Functional: File uploads work correctly — the error is cosmetic
- UX: Users see an error message that suggests failure when the operation actually succeeds
- Trust: Users may retry, causing duplicate uploads
Environment
- OpenClaw msteams plugin (
@openclaw/msteams) - Bot Framework:
@microsoft/agents-hosting - Teams client: Desktop
- Chat type: Personal (1:1 DM)