Skip to content

[msteams] FileConsent invoke response timing causes 'Something went wrong' on file uploads #27632

@cwatts-sage

Description

@cwatts-sage

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

  1. Send a file (e.g., PDF) from the bot to a user in a DM
  2. Bot sends FileConsentCard ("Bot needs permission to upload...")
  3. User clicks "Allow"
  4. Observed: "Something went wrong. Please try again." error banner appears
  5. 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)

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions