fishaudio/fish-speech · error · HTTPException

Unsupported Media Type

Error message

Unsupported Media Type

What it means

The server's request-body parser only supports application/msgpack, application/json, and multipart/form-data; any other Content-Type raises 415 Unsupported Media Type with an Accept header listing what it will take.

Source

Thrown at tools/server/api_utils.py:64

class MsgPackRequest(HttpRequest):
    async def data(
        self,
    ) -> Annotated[
        Any,
        ContentType("application/msgpack"),
        ContentType("application/json"),
        ContentType("multipart/form-data"),
    ]:
        if self.content_type == "application/msgpack":
            return ormsgpack.unpackb(await self.body)

        elif self.content_type == "application/json":
            return await self.json

        elif self.content_type == "multipart/form-data":
            return await self.form

        raise HTTPException(
            HTTPStatus.UNSUPPORTED_MEDIA_TYPE,
            headers={
                "Accept": "application/msgpack, application/json, multipart/form-data"
            },
        )


async def inference_async(req: ServeTTSRequest, engine: TTSInferenceEngine):
    for chunk in inference(req, engine):
        print("Got chunk")
        if isinstance(chunk, bytes):
            yield chunk


async def buffer_to_async_generator(buffer):
    yield buffer

View on GitHub (pinned to befe400174)

Solutions

  1. Set Content-Type: application/json (or msgpack for binary efficiency, multipart for file uploads)
  2. For curl add -H 'Content-Type: application/json' alongside --data
  3. Inspect the response's Accept header to see accepted types

Example fix

# before
curl -X POST url/v1/tts --data '{...}'
# after
curl -X POST url/v1/tts -H 'Content-Type: application/json' --data '{...}'
Defensive patterns

Strategy: validation

Validate before calling

assert req.headers.get("content-type", "").split(";")[0] in {
    "application/msgpack", "application/json", "multipart/form-data"
}

Try / catch

if resp.status_code == 415:
    resp = requests.post(url, json=payload)  # retry with correct content type

Prevention

When it happens

Trigger: POSTing to an endpoint with Content-Type: text/plain, application/x-www-form-urlencoded, or a missing/misspelled content type.

Common situations: Custom HTTP clients defaulting to form encoding; curl without -H 'Content-Type: application/json'; proxies/gateways rewriting the header.

Related errors


AI-assisted analysis of fishaudio/fish-speech@befe400174 (2026-08-27). Data as JSON: /api/errors/b69fee9f98e38e0e. Report an issue: GitHub.