#16791: fix(discord): use rawBody with explicit Content-Type for voice message uploads
channel: discord
stale
size: XS
Cluster:
Discord and MS Teams Fixes
Fixes #16762
## Problem
Discord voice messages fail with HTTP 400 error: Expected Content-Type header to be one of application/json.
## Root Cause
When calling rest.post with body containing a files field, Carbon (@buape/carbon) auto-detects it and switches to FormData mode (multipart/form-data). However, Discord /attachments endpoint requires application/json and rejects FormData.
## Solution
Use rawBody with pre-serialized JSON and explicit Content-Type: application/json header to bypass Carbon automatic FormData detection.
## Changes
- Changed rest.post call to use rawBody instead of body
- Added explicit Content-Type: application/json header
- Added comment explaining why this is necessary
## Testing
This fix ensures Discord voice messages can be sent successfully without HTTP 400 errors.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes Discord voice message uploads failing with HTTP 400 (`Expected Content-Type header to be one of application/json`). The `/channels/{channelId}/attachments` endpoint expects a JSON body with file metadata (`filename`, `file_size`, `id`), but Carbon's `RequestClient` auto-detects the `files` key in `body` and switches to `multipart/form-data`. The fix uses `rawBody` with `JSON.stringify` and an explicit `Content-Type: application/json` header to bypass Carbon's auto-detection.
- Switched from `body` to `rawBody` with pre-serialized JSON for the upload URL request (Step 1)
- Added explicit `Content-Type: application/json` header
- Added explanatory comment documenting the workaround
- Step 3 (message creation) is unaffected since it uses `attachments`, not `files`
- The `rawBody` and `headers` options are already used elsewhere in the codebase (`send.guild.ts`), confirming API compatibility
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it's a targeted, well-documented fix for a clear API compatibility issue.
- The change is minimal (3 lines of logic + 2 comment lines), addresses a concrete HTTP 400 error with a well-understood root cause, and uses established patterns already present in the codebase (rawBody and headers options). No new dependencies, no behavioral changes beyond fixing the broken endpoint call.
- No files require special attention.
<sub>Last reviewed commit: ac5f162</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#22940: fix(discord): detect voice messages for preflight transcription bef...
by aldoeliacim · 2026-02-21
75.1%
#21230: Fix [Bug]: Discord attachments silently missing (Fixes #19956)
by vasujain00 · 2026-02-19
71.0%
#20913: fix: intercept Discord embed images to enforce mediaMaxMb
by MumuTW · 2026-02-19
70.7%
#17648: fix: Discord guild channel detection using rawMessage.guild_id
by MisterGuy420 · 2026-02-16
70.5%
#21463: fix(discord): prevent WebSocket death spiral + fix numeric channel ID…
by akropp · 2026-02-20
69.7%
#20488: fix(discord): pass mediaLocalRoots to sendMessageDiscord
by olyashok · 2026-02-19
69.3%
#15900: fix(discord): filter bot's own messages early to prevent self-DoS
by Shuai-DaiDai · 2026-02-14
69.2%
#21466: Copilot/fix forwarded message visibility
by stnguyen90 · 2026-02-20
69.0%
#21898: fix(telegram): auto-detect captionable messages for editMessageCaption
by ptrkstr · 2026-02-20
68.3%
#22557: fix(discord): coerce exec approval approver IDs to string to preven...
by zwffff · 2026-02-21
68.2%