fix(stream): chat insert 400 — insert body must declare snippet.type

The liveChatId fix (TASK 44) worked on the next Test Stream, but every Mock
Chat Input send returned 'YouTube rejected the message (error 400)'. The
runtime log's body: 400 MISSING_REQUIRED_FIELD, domain
youtube.api.v3.LiveChatMessageInsertResponse.Error.

The liveChat/messages.insert snippet requires type ('textMessageEvent' or
'pollEvent') alongside liveChatId and textMessageDetails.messageText; the
TASK 41 body omitted it, and the Good Dog test asserted only liveChatId +
messageText were present — false-green while real YouTube rejected every
send. Fix body + assert type in the same test so the field can never drop
silently again.

Reference: https://developers.google.com/youtube/v3/live/docs/liveChatMessages/insert

Good Dog: ONE integration test (strengthened TestStream_DockTooling...).
Gate: clean build 0 warnings; full vstest 317/318 (the 1 failure is the
known environmental RealMouseDrag flake — passes 3/3 in isolation).
This commit is contained in:
2026-09-25 08:12:05 -07:00
parent 94f015044a
commit 0981a72eea
7 changed files with 101 additions and 33 deletions
+41
View File
@@ -0,0 +1,41 @@
# TASK 45 — TEST-tab chat fix #2: insert body must declare `snippet.type`
> Catalog: [`TASKS.md`](../TASKS.md). Status: ✅ **SHIPPED 2026-09-25** — the live
> "YouTube rejected the message (error 400)" report from the creator's Test Stream run
> after TASK 44 shipped.
## Provenance
- **2026-09-25, creator run:** TASK 44's liveChatId fix worked — the drawer opened
with a resolved liveChatId and Mock Chat Input became enabled — but every send was
rejected: `YouTube rejected the message (error 400)`. The runtime log
(`%APPDATA%\ytLlive\startup.log`) captured the body: `400
MISSING_REQUIRED_FIELD`, `domain: youtube.api.v3.LiveChatMessageInsertResponse.Error`.
- **Diagnosis:** the official `liveChatMessages.insert` reference lists three
**required** snippet properties: `liveChatId`, **`type`** (`textMessageEvent` or
`pollEvent`), and `textMessageDetails.messageText` (if text). The TASK 41 body sent
only `liveChatId` + `textMessageDetails`, omitting `type`. The TASK 41 Good Dog test
asserted the body contained `liveChatId` + `messageText` — but never `type` — so it
stayed **false-green** while real YouTube rejected every insert.
## What shipped
- `Services/YouTubeStreamService.cs` — `InsertChatMessageAsync`: the POST body now
includes **`type = "textMessageEvent"`** in the snippet.
- `ytLive.Tests/TestStreamTests.cs` — the TASK 41 test's POST-body assertion now also
asserts `"type":"textMessageEvent"` is present (the false-green fixed at its source:
assertion = WHAT WE SEND must mirror YouTube's required fields).
- Docs: `ai.md` (Test Stream section), `TASKS.md` (row 45), `HANDOFF.md` rewritten,
`MyMistakes.md` recipe added.
## Validation (Good Dog: ONE integration test)
The strengthened `TestStream_DockTooling_And_ThreeWayDrawerExclusivity` — the existing
TASK 41 insert-to-HTTP assertion now fails if `type` is ever dropped again.
**Gate: clean build 0 warnings; full vstest passed (count recorded in HANDOFF).**
## Reference
- https://developers.google.com/youtube/v3/live/docs/liveChatMessages/insert (required
props include `snippet.type`; `textMessageEvent` or `pollEvent`)