Bug Description
The Google Chat plugin passes raw message IDs (or session-derived thread IDs) as the thread.name field in the Google Chat API spaces.messages.create call. The Google Chat API requires thread names in spaces/{space}/threads/{thread} format, causing a 400 error:
Google Chat API 400: {
"error": {
"code": 400,
"message": "The request contains an invalid thread resource name",
"status": "INVALID_ARGUMENT"
}
}
Root Cause
In extensions/googlechat/src/channel.ts, the sendText function (line ~373):
const thread = (threadId ?? replyToId ?? undefined) as string | undefined;
This passes whatever threadId or replyToId the routing layer provides directly to sendGoogleChatMessage(), which then sets:
body.thread = { name: thread };
The value being passed is not a valid Google Chat thread resource name (spaces/xxx/threads/yyy), so the API rejects it.
Impact
- With
replyToMode: "first" or "all": Messages sometimes succeed (Google Chat creates threads) but the threading behavior is undesirable for DM conversations
- With
replyToMode: "off": replyToId is suppressed, but threadId from the session context still leaks through, causing the same 400 error on every message send — the bot goes completely silent
streamMode: "replace": The updateGoogleChatMessage call also fails when the initial message was created with an invalid thread reference
blockStreaming: true: Does not fix the issue since the thread name is constructed in the base sendText path
Expected Behavior
- When
replyToMode is "off", no thread field should be included in the API request
- When
replyToMode is "first" or "all", the thread field should contain a properly formatted Google Chat thread resource name (spaces/{space}/threads/{thread}), not a raw message ID
- DM conversations should work without forced threading
Environment
- OpenClaw version: 2026.3.7
- Google Chat configured with service account,
audienceType: "app-url"
- DM mode with pairing policy
Workaround
Currently the only working configuration is replyToMode: "first" with streamMode: "replace", which sends messages but forces them into threads. There is no config-only fix to get flat (non-threaded) DM responses.
Config Tested
{
"replyToMode": "off", // bot goes silent (400 errors on every send)
"replyToMode": "first", // works but creates threads
"blockStreaming": true, // does not fix the threading issue
"streamMode": "status_final" // does not fix the threading issue
}
Bug Description
The Google Chat plugin passes raw message IDs (or session-derived thread IDs) as the
thread.namefield in the Google Chat APIspaces.messages.createcall. The Google Chat API requires thread names inspaces/{space}/threads/{thread}format, causing a 400 error:Root Cause
In
extensions/googlechat/src/channel.ts, thesendTextfunction (line ~373):This passes whatever
threadIdorreplyToIdthe routing layer provides directly tosendGoogleChatMessage(), which then sets:The value being passed is not a valid Google Chat thread resource name (
spaces/xxx/threads/yyy), so the API rejects it.Impact
replyToMode: "first"or"all": Messages sometimes succeed (Google Chat creates threads) but the threading behavior is undesirable for DM conversationsreplyToMode: "off":replyToIdis suppressed, butthreadIdfrom the session context still leaks through, causing the same 400 error on every message send — the bot goes completely silentstreamMode: "replace": TheupdateGoogleChatMessagecall also fails when the initial message was created with an invalid thread referenceblockStreaming: true: Does not fix the issue since the thread name is constructed in the basesendTextpathExpected Behavior
replyToModeis"off", nothreadfield should be included in the API requestreplyToModeis"first"or"all", thethreadfield should contain a properly formatted Google Chat thread resource name (spaces/{space}/threads/{thread}), not a raw message IDEnvironment
audienceType: "app-url"Workaround
Currently the only working configuration is
replyToMode: "first"withstreamMode: "replace", which sends messages but forces them into threads. There is no config-only fix to get flat (non-threaded) DM responses.Config Tested
{ "replyToMode": "off", // bot goes silent (400 errors on every send) "replyToMode": "first", // works but creates threads "blockStreaming": true, // does not fix the threading issue "streamMode": "status_final" // does not fix the threading issue }