Skip to content

Fix Teams 413 error: add charset=utf-8 to Content-Type header and retry on 413#2162

Open
devin-ai-integration[bot] wants to merge 2 commits intomasterfrom
devin/1774046106-fix-teams-413-charset
Open

Fix Teams 413 error: add charset=utf-8 to Content-Type header and retry on 413#2162
devin-ai-integration[bot] wants to merge 2 commits intomasterfrom
devin/1774046106-fix-teams-413-charset

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Mar 20, 2026

Summary

Fixes persistent HTTP 413 (Request Entity Too Large) errors from Microsoft Teams webhooks, even after the payload truncation logic from #2160.

Root cause: The Teams webhook connector converts the request body to UTF-16 when charset is not specified in the Content-Type header, effectively doubling the payload size before enforcing the 28KB limit. A 14KB payload becomes ~28KB after conversion, triggering a 413. (Source)

Changes:

  1. Set Content-Type: application/json; charset=utf-8 so the connector skips the UTF-16 conversion
  2. Added a retry safety net: if Teams still returns a 413 in the response body (old webhook connectors return HTTP 200 with error text), retry once with a minimal card

Review & Testing Checklist for Human

  • Verify the charset=utf-8 fix works with Prendio's specific webhook type (old O365 connector vs new Power Automate workflow webhook — behavior may differ)
  • Check that the "413" in response.text substring match won't false-positive on legitimate response text from Teams
  • Confirm that the retry's _minimal_card(card) fallback produces a payload small enough for Teams in all cases (it uses **card which preserves non-body fields)
  • Trigger or wait for the next Prendio DAG run after deployment and verify alerts are delivered successfully

Notes

  • The charset fix is based on community findings (SO answer), not official Microsoft documentation. It should be monitored after deployment.
  • If the retry also fails with a 413-in-body response, it falls through to the existing error handling in send_message — no behavior regression.
  • No unit tests were added; the fix is best validated by a production run against the Prendio webhook.

Link to Devin session: https://app.devin.ai/sessions/d746de1f2743489995cc5070957c91c6

Summary by CodeRabbit

  • Bug Fixes
    • Improved Teams messaging integration to automatically retry with a compact card format when service responses indicate payload-size issues, increasing delivery reliability.
    • Added request timeouts to avoid long waits and ensured UTF-8 content encoding in outgoing requests for better compatibility.

…ry on 413

Co-Authored-By: Michael Myaskovsky <michael@elementary-data.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@github-actions
Copy link
Contributor

👋 @devin-ai-integration[bot]
Thank you for raising your pull request.
Please make sure to add tests and document all user-facing changes.
You can do this by editing the docs files in this pull request.

@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba3516b1-3859-4d7c-aa1f-7d02c28bf195

📥 Commits

Reviewing files that changed from the base of the PR and between a715f67 and 49a3dbd.

📒 Files selected for processing (1)
  • elementary/messages/messaging_integrations/teams_webhook.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • elementary/messages/messaging_integrations/teams_webhook.py

📝 Walkthrough

Walkthrough

The Teams webhook handler now sets Content-Type: application/json; charset=utf-8, applies a request timeout, and retries with a minimal AdaptiveCard payload if an HTTP 200 response body contains "413", logging a warning before the retry. (50 words)

Changes

Cohort / File(s) Summary
Teams Webhook Error Handling
elementary/messages/messaging_integrations/teams_webhook.py
Added REQUEST_TIMEOUT_SECONDS and applied timeout to requests.post. Updated Content-Type to include charset=utf-8. Changed _minimal_card to explicitly set "type": "AdaptiveCard" and "version". After a successful initial POST, if response is 200, response body length > 1, and contains "413", log a warning and resend with a minimal-card payload; retry response is returned.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I tapped the webhook, hopeful and bright,
The server sighed "413" in the night,
I trimmed the card, set UTF-8 neat,
I retried with patience — message complete! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main changes: adding charset=utf-8 to Content-Type header and implementing a retry mechanism for 413 errors in Teams webhook integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1774046106-fix-teams-413-charset

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@elementary/messages/messaging_integrations/teams_webhook.py`:
- Around line 122-123: The retry payload still contains large top-level fields
because _minimal_card(card) clones the entire original card and only swaps out
body; change _minimal_card to build and return a brand-new minimal dict (do not
copy the original) that includes only the small required keys (e.g., card
type/summary/title if needed) plus the new body, ensuring any large fields from
the original card are omitted before calling _build_payload; update callers
using _minimal_card(card) accordingly so payload only contains those minimal
keys.
- Around line 107-128: The two requests.post calls that send Teams webhooks (the
initial call and the retry in the branch that builds a minimal card) lack an
explicit timeout and can block indefinitely; update both calls to pass a
reasonable timeout value (e.g. timeout=5 or a configured constant) to
requests.post so the worker won't hang, and ensure the same timeout constant is
used for both the initial send and the retry paths that call _build_payload and
_minimal_card.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 72f4a384-745c-4c03-816c-fd7c00202f35

📥 Commits

Reviewing files that changed from the base of the PR and between ed170b7 and a715f67.

📒 Files selected for processing (1)
  • elementary/messages/messaging_integrations/teams_webhook.py

Co-Authored-By: Michael Myaskovsky <michael@elementary-data.com>
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.

0 participants