{"record":{"id":"869a3cdfb10a5604","repo":"fishaudio/fish-speech","slug":"streaming-only-supports-wav-format","errorCode":null,"errorMessage":"Streaming only supports WAV format","messagePattern":"Streaming only supports WAV format","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"tools/server/views.py","lineNumber":167,"sourceCode":"    Generate speech from text using TTS model.\n    \"\"\"\n    try:\n        # Get the model from the app\n        app_state = request.app.state\n        model_manager: ModelManager = app_state.model_manager\n        engine = model_manager.tts_inference_engine\n        sample_rate = engine.decoder_model.sample_rate\n\n        # Check if the text is too long\n        if app_state.max_text_length > 0 and len(req.text) > app_state.max_text_length:\n            raise HTTPException(\n                HTTPStatus.BAD_REQUEST,\n                content=f\"Text is too long, max length is {app_state.max_text_length}\",\n            )\n\n        # Check if streaming is enabled\n        if req.streaming and req.format != \"wav\":\n            raise HTTPException(\n                HTTPStatus.BAD_REQUEST,\n                content=\"Streaming only supports WAV format\",\n            )\n\n        # Perform TTS\n        if req.streaming:\n            return StreamResponse(\n                iterable=inference_async(req, engine),\n                headers={\n                    \"Content-Disposition\": f\"attachment; filename=audio.{req.format}\",\n                },\n                content_type=get_content_type(req.format),\n            )\n        else:\n            fake_audios = next(inference(req, engine))\n            buffer = io.BytesIO()\n            sf.write(\n                buffer,","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/fishaudio/fish-speech/blob/befe4001745417f8c42131739d862b8a6fdbd15a/tools/server/views.py#L149-L185","documentation":"Raised by the TTS endpoint when the request sets streaming=true but format is anything other than \"wav\". Streaming synthesis emits PCM/WAV chunks incrementally, which is not possible for formats that require post-encoding (e.g. mp3).","triggerScenarios":"POST /v1/tts with {\"streaming\": true, \"format\": \"mp3\"} (or opus/flac/etc.). Any format value != \"wav\" combined with streaming triggers HTTP 400.","commonSituations":"Clients copying an OpenAI TTS example that requests mp3 and then adding streaming=true; assuming all formats stream; case-sensitivity issues (\"WAV\" vs \"wav\").","solutions":["Set format to \"wav\" (lowercase) when streaming is enabled.","Disable streaming (streaming=false) if you need mp3 or another encoded format; the whole file is returned after synthesis."],"exampleFix":"# before\n{\"text\": \"hi\", \"streaming\": True, \"format\": \"mp3\"}\n\n# after\n{\"text\": \"hi\", \"streaming\": True, \"format\": \"wav\"}","handlingStrategy":"validation","validationCode":"def normalize(req):\n    if req.get(\"streaming\"):\n        req[\"format\"] = \"wav\"\n    return req","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to wav for streaming requests","Treat 400s as client bugs to fix in the request builder, not retry"],"tags":["tts","streaming","format-mismatch","http-400"],"backgroundTag":"unsupported-media-format","analyzedSha":"befe4001745417f8c42131739d862b8a6fdbd15a","analyzedAt":"2026-08-27T21:31:45.703Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}