Summary
When a user opens our line of business bot through the Teams client's own Search or New chat surface, the client composes a member MRI with five colon separated parts. The Teams chat service then rejects that identifier as malformed, and messages typed into the resulting conversation fail to send. Microsoft documents exactly one bot member MRI form, the two part 28:<botId>. The string the client generates corresponds to nothing in the published format.
The producer of the identifier and the component that rejects it are both first party. Our app supplies a manifest. It does not compose member MRIs and it does not decide what the search surface hands to the chat service.
Environment
| Item |
Value |
| Product |
Microsoft Teams, web and desktop client |
| -------- |
-------- |
| Product |
Microsoft Teams, web and desktop client |
| App type |
Custom line of business app, single tenant |
| App version |
0.1.5 |
| First observed |
22 July 2026 |
Tenant ID, user object ID, bot App ID, Teams catalog app ID and manifest external ID are withheld from this post and supplied on request. Placeholders below stand for real GUIDs. The same placeholder always means the same value.
Steps to reproduce
- Sign in to Teams as a user who has the app installed.
- Open Search or New chat and type the app's display name.
- Two identical results appear for the app, though the user holds a single installation.
- Select a result to open the personal bot chat.
- Type any message and press Send.
Observed result
The client composes this member MRI, with the two GUIDs replaced by placeholders:
28:<bot-app-id>:appId:<teams-catalog-app-id>
Both are standard 36 character GUIDs. The literal string :appId: sits between them.
The chat service rejects it:
errorCode: 201
errorSubCode: 1
Invalid member MRI format: >3 parts split by ':'
The message is marked "Failed to send" in the composer, with retry and delete controls beside it. Screenshot attached.
Expected result
The client composes a member MRI the chat service accepts, and the message sends.
What Microsoft Graph already confirms
Microsoft support asked for these checks before routing the case here. All three came back clean.
GET /users/{user-id}/teamwork/installedApps?$expand=teamsAppDefinition($expand=bot) returns exactly one installation of the app for the affected user, and its bot resolves to a single bot object whose id matches the bot App ID declared in the manifest exactly.
GET /users/{user-id}/teamwork/installedApps/{installationId}/chat returns a valid one on one chat, chatType: oneOnOne, isHiddenForAllMembers: false.
Opening that Graph provided webUrl while signed in as the affected user loads the existing bot conversation with full history, and renders the composer and Send control without error.
No Graph call in this case fails.
What that rules out
There is no duplicate installation, the installed app maps to the correct bot, and the personal chat object exists and is reachable. The customer side explanations for a broken bot chat do not hold. The failure sits in how the Teams client resolves a bot identity from its search surface, or in the server side data that surface reads.
What I have not established
I have not sent a message through the Graph resolved chat, only opened it. Opening a chat is a read. Whether that path accepts a write is untested, so I make no claim that it is a working workaround.
I have not queried the tenant app catalog. The checks above cover installedApps, which is a user to app link, not appCatalogs/teamsApps, which is what the search surface reads.
Likely cause, unconfirmed
The duplicate search result is the one detail nothing else accounts for. A single installed app producing two identical entries in Search is server side data, and nothing in a tenant app can write a second entry there.
If one bot ID resolves to more than one catalog entry, the search layer has to indicate which entry the user selected, and appending the catalog teamsAppId to the bot MRI is an obvious way to do it. That produces exactly the observed five part string, and exactly the string the chat service was never built to parse. Graph makes this state easy to reach without noticing, since teamsApp.id is server generated while the manifest id is stamped as externalId, so uploading one package by two routes creates two catalog IDs for one bot with nothing in the installation list to show for it.
This fits every observed fact, including the clean installation check. It is unproven until I run the catalog query.
Questions
- Is
28:{botId}:appId:{teamsAppId} a documented or supported member MRI form? The deep link reference publishes only the two part 28:<botId>, and the chat service error indicates it accepts at most three parts.
- Under what conditions does the client append
:appId:{teamsAppId} to a bot MRI? If it is disambiguation between catalog entries, why is the result an identifier the chat service rejects?
- Is a single bot present in more than one tenant catalog entry, for example sideloaded alongside organization published, a supported state? If it is, the client resolving it into a malformed identifier looks like a defect. If it is not, that constraint does not appear to be documented.
- Is the correct guidance that bots should never be opened through Search or New chat, and that products should ship the documented two part deep link instead? If so, that is worth stating explicitly in the bot deployment documentation.
I searched Microsoft Q&A, Microsoft Learn, Stack Overflow, and the MicrosoftDocs/msteams-docs and OfficeDev/Microsoft-Teams-Samples repositories before posting. The error string and the five part MRI shape return no public hits.
Happy to supply the full identifier set, an in client Report a problem feedback ID, or a fresh reproduction on request.
Body
Summary
When a user opens our line of business bot through the Teams client's own Search or New chat surface, the client composes a member MRI with five colon separated parts. The Teams chat service then rejects that identifier as malformed, and messages typed into the resulting conversation fail to send. Microsoft documents exactly one bot member MRI form, the two part 28:<botId>. The string the client generates corresponds to nothing in the published format.
The producer of the identifier and the component that rejects it are both first party. Our app supplies a manifest. It does not compose member MRIs and it does not decide what the search surface hands to the chat service.
Environment
| Item |
Value |
| Product |
Microsoft Teams, web and desktop client |
| App type |
Custom line of business app, single tenant |
| App version |
0.1.5 |
| First observed |
22 July 2026 |
Tenant ID, user object ID, bot App ID, Teams catalog app ID and manifest external ID are withheld from this post and supplied on request. Placeholders below stand for real GUIDs. The same placeholder always means the same value.
Steps to reproduce
- Sign in to Teams as a user who has the app installed.
- Open Search or New chat and type the app's display name.
- Two identical results appear for the app, though the user holds a single installation.
- Select a result to open the personal bot chat.
- Type any message and press Send.
Observed result
The client composes this member MRI, with the two GUIDs replaced by placeholders:
28:<bot-app-id>:appId:<teams-catalog-app-id>
Both are standard 36 character GUIDs. The literal string :appId: sits between them.
The chat service rejects it:
errorCode: 201
errorSubCode: 1
Invalid member MRI format: >3 parts split by ':'
The message is marked "Failed to send" in the composer, with retry and delete controls beside it. Screenshot attached.
Expected result
The client composes a member MRI the chat service accepts, and the message sends.
What Microsoft Graph already confirms
Microsoft support asked for these checks before routing the case here. All three came back clean.
GET /users/{user-id}/teamwork/installedApps?$expand=teamsAppDefinition($expand=bot) returns exactly one installation of the app for the affected user, and its bot resolves to a single bot object whose id matches the bot App ID declared in the manifest exactly.
GET /users/{user-id}/teamwork/installedApps/{installationId}/chat returns a valid one on one chat, chatType: oneOnOne, isHiddenForAllMembers: false.
Opening that Graph provided webUrl while signed in as the affected user loads the existing bot conversation with full history, and renders the composer and Send control without error.
No Graph call in this case fails.
What that rules out
There is no duplicate installation, the installed app maps to the correct bot, and the personal chat object exists and is reachable. The customer side explanations for a broken bot chat do not hold. The failure sits in how the Teams client resolves a bot identity from its search surface, or in the server side data that surface reads.
What I have not established
I have not sent a message through the Graph resolved chat, only opened it. Opening a chat is a read. Whether that path accepts a write is untested, so I make no claim that it is a working workaround.
I have not queried the tenant app catalog. The checks above cover installedApps, which is a user to app link, not appCatalogs/teamsApps, which is what the search surface reads.
Likely cause, unconfirmed
The duplicate search result is the one detail nothing else accounts for. A single installed app producing two identical entries in Search is server side data, and nothing in a tenant app can write a second entry there.
If one bot ID resolves to more than one catalog entry, the search layer has to indicate which entry the user selected, and appending the catalog teamsAppId to the bot MRI is an obvious way to do it. That produces exactly the observed five part string, and exactly the string the chat service was never built to parse. Graph makes this state easy to reach without noticing, since teamsApp.id is server generated while the manifest id is stamped as externalId, so uploading one package by two routes creates two catalog IDs for one bot with nothing in the installation list to show for it.
This fits every observed fact, including the clean installation check. It is unproven until I run the catalog query.
Questions
- Is
28:{botId}:appId:{teamsAppId} a documented or supported member MRI form? The deep link reference publishes only the two part 28:<botId>, and the chat service error indicates it accepts at most three parts.
- Under what conditions does the client append
:appId:{teamsAppId} to a bot MRI? If it is disambiguation between catalog entries, why is the result an identifier the chat service rejects?
- Is a single bot present in more than one tenant catalog entry, for example sideloaded alongside organization published, a supported state? If it is, the client resolving it into a malformed identifier looks like a defect. If it is not, that constraint does not appear to be documented.
- Is the correct guidance that bots should never be opened through Search or New chat, and that products should ship the documented two part deep link instead? If so, that is worth stating explicitly in the bot deployment documentation.
I searched Microsoft Q&A, Microsoft Learn, Stack Overflow, and the MicrosoftDocs/msteams-docs and OfficeDev/Microsoft-Teams-Samples repositories before posting. The error string and the five part MRI shape return no public hits.
Happy to supply the full identifier set, an in client Report a problem feedback ID, or a fresh reproduction on request.