Skip to content

fix: reject empty TTS text at the schema boundary (Fixes #946) - #1303

Open
MushiSenpai wants to merge 1 commit into
fishaudio:mainfrom
MushiSenpai:fix/validate-empty-tts-text-946
Open

fix: reject empty TTS text at the schema boundary (Fixes #946)#1303
MushiSenpai wants to merge 1 commit into
fishaudio:mainfrom
MushiSenpai:fix/validate-empty-tts-text-946

Conversation

@MushiSenpai

Copy link
Copy Markdown

Is this a feature or a BUG fix? BUG fix.

Related issue: Fixes #946

Summary

POST /v1/tts returns an HTTP 500 with a JSON error body when text is empty.
A client that streams the response then writes that JSON error into a .wav file.

Root cause is a schema asymmetry in fish_speech/utils/schema.py:

  • ServeTTSRequest.text was an unconstrained str, so an empty string passes
    validation and flows into synthesis.
  • Empty text yields zero audio segments, which TTSInferenceEngine.inference
    reports as an error and tools/server/inference.py re-raises as
    HTTPException(INTERNAL_SERVER_ERROR) → the 500 reported in baize.exceptions.HTTPException: (500, "'No audio generated, please check the input text.'") #946
    ("No audio generated, please check the input text.").
  • The sibling model AddReferenceRequest.text already constrains
    min_length=1, so the asymmetry is the bug.

The fix

Constrain ServeTTSRequest.text the same way, so empty input is rejected with a
clean 4xx validation error at the request boundary — before any model work:

# fish_speech/utils/schema.py
class ServeTTSRequest(BaseModel):
-    text: str
+    text: str = Field(..., min_length=1)

One line, no behavior change for valid input. Matches the existing min_length=1
on AddReferenceRequest.text and the Field(...) constraint style already used on
ServeTTSRequest (top_p, temperature, repetition_penalty).

Validation

The change is pure pydantic validation (no model weights needed). Importing the
model and constructing it:

Input Before After
text="" accepted → empty segments → HTTP 500 ValidationError (clean 4xx)
text="hello" accepted accepted (unchanged)

Scope

This fixes the empty-string trigger at the schema boundary. The broader
"no segments generated → 500" path (e.g. other degenerate inputs) is a separate,
larger change in tools/server/inference.py and is intentionally out of scope here.


Disclosure: this fix was drafted with AI assistance (Claude) and reviewed, tested,
and submitted by me. The commit carries a Co-Authored-By trailer.

ServeTTSRequest.text was an unconstrained `str`, so empty text reached synthesis,
produced zero audio segments, and surfaced as an HTTP 500 with a JSON error body
(issue fishaudio#946) which a streaming client then writes as a .wav. The sibling
AddReferenceRequest.text already constrains min_length=1; apply the same to
ServeTTSRequest.text so empty input is rejected with a clean 4xx at the boundary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale label Jul 28, 2026
@MushiSenpai

MushiSenpai commented Aug 13, 2026

Copy link
Copy Markdown
Author

Still applies to current main: ServeTTSRequest.text is a bare str at fish_speech/utils/schema.py:82, while the sibling AddReferenceRequest.text already carries min_length=1. This one-line change just restores that symmetry, so an empty text fails validation with a clean 4xx instead of surfacing as an HTTP 500 whose JSON body streaming clients happily write out as a .wav.

No behavior change for valid requests. Happy to rebase if that helps.

@github-actions github-actions Bot removed the stale label Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

baize.exceptions.HTTPException: (500, "'No audio generated, please check the input text.'")

1 participant