Skip to content

Make channelData subfields optional to avoid throw - #564

Merged
Corina (corinagum) merged 1 commit into
mainfrom
cg/fix/empty-inbound-objects
Aug 18, 2026
Merged

Make channelData subfields optional to avoid throw#564
Corina (corinagum) merged 1 commit into
mainfrom
cg/fix/empty-inbound-objects

Conversation

@corinagum

Copy link
Copy Markdown
Contributor

Fixes #563

The Teams service can send nested channelData objects as empty objects ( {} ). Because AppInfo.id was required, Pydantic raised a ValidationError, and since ActivityTypeAdapter.validate_python has no fallback, the entire activity was rejected, so affected bots silently stopped responding.

Reported against 2.0.15, the first release containing #504. Confirmed to affect customers, currently in 1:1 chats, with exposure growing as an upstream server-side rollout ramps.

Root cause

channelData.app is optional, so an absent app was always fine, but a present but empty one wasn't. Auditing the model graph showed this isn't unique to app: 98 sites exist where an optional parent points at a child with required fields. Seven were reachable from a plain message activity:

channelData.app={}       -> channelData.app.id            Field required
channelData.channel={}   -> channelData.channel.id        Field required
channelData.team={}      -> channelData.team.id           Field required
channelData.tenant={}    -> channelData.tenant.id         Field required
channelData.settings={}  -> channelData.settings.selectedChannel
attachments=[{}]         -> attachments.0.contentType
entities=[{}]            -> entities.0._unknown.type

Change

Make these inbound-only fields optional: AppInfo.id, ChannelInfo.id, TeamInfo.idTenantInfo.id, ChannelDataSettings.selected_channel, Attachment.content_type, EntityBase.type.

MessageUpdateChannelData and MessageDeleteChannelData both inherit ChannelData, so they're covered without separate edits.

EntityBase.type is relaxed at the base rather than overridden on UnknownEntity: every concrete entity already overrides type with a Literal default, so UnknownEntity is the only class inheriting it raw. This also means an entity type introduced after this SDK version no longer drops the message.

Tests

New test_empty_inbound_objects.py covering each empty-object case, an unrecognized entity type, that populated values still parse, and that absent channelData is unchanged.

Validation

  • 852 tests pass across packages/api + packages/apps 
  • ruff format  / ruff check  clean
  • pyright: zero net new errors

Notes

This is the defensive half. The empty object is a service-side wire-contract issue and has been raised with that team separately; this change means the SDK degrades gracefully regardless.

Copilot AI lite review requested due to automatic review settings August 17, 2026 19:43

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.

Pull request overview

This PR addresses a regression where inbound Activities could be rejected entirely due to ValidationError when Microsoft Teams sends certain nested objects as empty {} (notably under channelData, plus empty attachments / entities). It relaxes several model fields so inbound parsing degrades gracefully instead of dropping the activity, and adds targeted unit tests to lock in the behavior (fixing #563).

Changes:

  • Relaxed several channelData-related nested model fields to be optional so empty {} no longer fails validation (AppInfo.id, ChannelInfo.id, TeamInfo.id, TenantInfo.id, ChannelDataSettings.selected_channel).
  • Relaxed Attachment.content_type and EntityBase.type to be optional so empty attachment/entity objects and forward-compatible entity types can parse.
  • Added new unit tests covering the empty-object cases and a future/unknown entity type.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/api/tests/unit/test_empty_inbound_objects.py Adds regression tests for empty nested inbound objects and unknown entity types.
packages/api/src/microsoft_teams/api/models/entity/entity_base.py Makes base entity type optional to allow unknown/empty entities to parse.
packages/api/src/microsoft_teams/api/models/channel_data/tenant_info.py Makes TenantInfo.id optional to tolerate empty tenant objects.
packages/api/src/microsoft_teams/api/models/channel_data/team_info.py Makes TeamInfo.id optional to tolerate empty team objects.
packages/api/src/microsoft_teams/api/models/channel_data/settings.py Makes selected_channel optional to tolerate empty settings objects.
packages/api/src/microsoft_teams/api/models/channel_data/channel_info.py Makes ChannelInfo.id optional to tolerate empty channel objects.
packages/api/src/microsoft_teams/api/models/channel_data/app_info.py Makes AppInfo.id optional to tolerate empty app objects.
packages/api/src/microsoft_teams/api/models/attachment/attachment.py Makes Attachment.content_type optional to tolerate empty attachment objects.

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

@corinagum
Corina (corinagum) merged commit 5fcd8fa into main Aug 18, 2026
9 checks passed
@corinagum
Corina (corinagum) deleted the cg/fix/empty-inbound-objects branch August 18, 2026 18:53
Corina (corinagum) added a commit that referenced this pull request Aug 19, 2026
Release 2.0.16: backport channelData optional-subfield fix (#564)
Corina (corinagum) added a commit that referenced this pull request Aug 19, 2026
Port channelData optional-subfield fix (#564) to 2.1 (2.1.0-alpha.2)
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.

[Bug]: ValidationError on MessageActivity

3 participants