Skip to content

fix(core): surface activity processing timeouts - #690

Merged
teddy arida-moody (teddyam) merged 7 commits into
mainfrom
teddyam-surface-activity-timeouts
Oct 2, 2026
Merged

teddy arida-moody (teddyam) merged 7 commits into
mainfrom
teddyam-surface-activity-timeouts

Conversation

@teddyam

@teddyam teddy arida-moody (teddyam) commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

When ProcessActivityTimeout elapsed, BotApplication.ProcessAsync logged the timeout and then returned normally, so the turn was reported as a success. HTTP returned 200, and Socket Mode replied or acked 200 (flagged in review on #686). This change makes timeouts fail visibly instead.

Change

The timeout catch in ProcessAsync(CoreActivity, ...) still writes the log, the HandlerErrors metric and the error span status. It then throws BotHandlerException("Activity processing timed out", new TimeoutException(...), activity).

No transport code changed. Each transport already handles BotHandlerException:

Path Before After
Socket Mode 200 reply/ack 500 reply ({ error = "bot handler error" } for invokes, 500 ack otherwise), plus the error hook
HTTP 200 500 if the response hasn't started, plus ASP.NET's unhandled-exception log
BotBuilder TeamsBotFrameworkHttpAdapter Silent success OnTurnError is called
TimeoutException thrown by a handler Wrapped as BotHandlerException("Error processing activity") Unchanged

The XML docs on both ProcessAsync overloads and on BotApplicationOptions.ProcessActivityTimeout now describe the new behavior.

Notes for reviewers

  • Deliberate behavior change: this reverses the earlier decision to treat a timeout as recoverable. docs/design-decouple-cancellation-token.md documented that decision; its timeout-handling section is updated in this PR to describe the new behavior.
  • Long-running streaming turns: a turn that runs past ProcessActivityTimeout (default 5 minutes) and observes its cancellation token, such as a long LLM stream, now fails instead of completing silently. It logs ActivityTimedOut at Error and returns a 500. On Socket Mode the 500 is sent as the envelope reply. On HTTP, Teams has usually closed the connection long before 5 minutes, so the 500 mainly shows up in server logs. Bots that legitimately need longer turns can raise ProcessActivityTimeout or set it to Timeout.InfiniteTimeSpan.
  • No timeout-specific exception type: the inner exception is a plain TimeoutException, and a TimeoutException thrown by a handler is wrapped the same way, so InnerException is TimeoutException does not identify a framework timeout. Transports don't need the distinction (both cases fail the turn), and logs already separate them (ActivityTimedOut, EventId 5, vs ActivityProcessingError, EventId 6, plus span status "timeout"). A public type such as ProcessActivityTimeoutException can be added later if a consumer needs to distinguish them in code.

Tests

  • Core: a timeout now throws from both the activity overload and the HTTP overload. The exception is a BotHandlerException with an inner TimeoutException and the activity attached. A handler that throws its own TimeoutException still gets the existing wrapping.
  • Apps: SocketModeServiceRegistration.DispatchAsync throws on timeout. The conversion to a 500 reply is already covered by SocketModeTransportTests.
  • BotBuilder: OnTurnError receives the timeout exception.

dotnet build Microsoft.Teams.slnx succeeds. Core (205) and Apps (829) unit tests pass on net8.0 and net10.0, and BotBuilder (57) passes on net10.0, the only framework it targets.

Teddy Arida-Moody and others added 2 commits October 1, 2026 16:39
When ProcessActivityTimeout elapses, BotApplication.ProcessAsync now throws
BotHandlerException wrapping a TimeoutException (with the activity attached)
instead of returning normally. HTTP returns 500, Socket Mode replies/acks 500,
and the BotBuilder adapter invokes OnTurnError, rather than reporting success.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 2, 2026 16:19
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

Review effort: Lite
Findings: 4 Medium severity

Open (4)
What changed in this PR

Makes ProcessActivityTimeout surface as a visible failure by throwing a BotHandlerException (with TimeoutException inner) instead of logging and returning successfully, ensuring transports report the turn as failed.

Changes:

  • Throw BotHandlerException("Activity processing timed out", inner: TimeoutException, activity) when processing exceeds ProcessActivityTimeout.
  • Update XML docs to describe timeout behavior on both ProcessAsync overloads and BotApplicationOptions.ProcessActivityTimeout.
  • Add unit tests validating timeout behavior across Core, Socket Mode hosting, and BotBuilder adapter (OnTurnError).
File Description
test/​Microsoft.Teams.Core.UnitTests/​BotApplicationTests.cs Adds/updates tests asserting timeouts now throw BotHandlerException with TimeoutException inner.
test/​Microsoft.Teams.Apps.UnitTests/​SocketMode/​SocketModeHostingTests.cs Adds Socket Mode dispatch test asserting timeout throws BotHandlerException.
test/​Microsoft.Teams.Apps.BotBuilder.UnitTests/​CompatAdapterTests.cs Adds adapter test asserting timeout flows to OnTurnError as BotHandlerException with TimeoutException inner.
src/​Microsoft.Teams.Core/​Hosting/​BotApplicationOptions.cs Documents that timeout elapsing results in a failing turn via thrown BotHandlerException.
src/​Microsoft.Teams.Core/​BotApplication.cs Updates docs and implements throwing behavior on activity processing timeout.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/Microsoft.Teams.Apps.BotBuilder.UnitTests/CompatAdapterTests.cs Outdated
Comment thread test/Microsoft.Teams.Core.UnitTests/BotApplicationTests.cs Outdated
Comment thread src/Microsoft.Teams.Core/BotApplication.cs Outdated
Comment thread src/Microsoft.Teams.Core/BotApplication.cs Outdated
Comment thread src/Microsoft.Teams.Core/BotApplication.cs

@corinagum Corina (corinagum) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could the description mention that long-running streaming turn after 5 mins now gets a 500?

Also, design docs on decoupling cancellation tokens are now stale. They need to be updated or removed.

Teddy Arida-Moody and others added 3 commits October 2, 2026 11:08
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread src/Microsoft.Teams.Core/BotApplication.cs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@corinagum Corina (corinagum) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, thanks!

Comment thread docs/design-decouple-cancellation-token.md
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teddyam
teddy arida-moody (teddyam) added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 8d47283 Oct 2, 2026
7 checks passed
@teddyam
teddy arida-moody (teddyam) deleted the teddyam-surface-activity-timeouts branch October 2, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants