fishaudio/fish-speech · error · ValueError
Either text or tokens must be provided
Error message
Either text or tokens must be provided
What it means
TextPart is a dataclass part of a ContentSequence that can represent content either as raw text or as pre-tokenized token IDs. In __post_init__, if both the text field and tokens field are left as None, the part has no content to encode, so a ValueError is raised. This protects downstream tokenization/encoding from receiving an empty part.
Source
Thrown at fish_speech/content_sequence.py:49
class VQPart(BasePart):
type = "vq"
codes: torch.Tensor
def __post_init__(self: "VQPart"):
self.type = "vq"
self.codes = restore_ndarray(self.codes, to_tensor=True)
@dataclass(kw_only=True)
class TextPart(BasePart):
type = "text"
text: str | None = None
tokens: list[int] | None = None
def __post_init__(self: "TextPart"):
self.type = "text"
if self.text is None and self.tokens is None:
raise ValueError("Either text or tokens must be provided")
@dataclass(kw_only=True)
class AudioPart(BasePart):
type = "audio"
features: torch.Tensor
def __post_init__(self: "AudioPart"):
self.type = "audio"
self.features = restore_ndarray(self.features, to_tensor=True)
@dataclass(kw_only=True)
class EncodedMessage:
tokens: torch.Tensor
labels: torch.Tensor
vq_mask_tokens: torch.Tensor | None = None
vq_mask_labels: torch.Tensor | None = NoneView on GitHub (pinned to befe400174)
Solutions
- Pass text="..." or tokens=[...] when creating TextPart; exactly one is required
- If generating parts dynamically, guard with `if not text and not tokens: continue` before appending the part
- Check for accidental None from upstream data sources (e.g. missing keys in JSON input) that feed into TextPart
Example fix
// before part = TextPart() # ValueError: Either text or tokens must be provided // after part = TextPart(text="hello") # or part = TextPart(tokens=[1, 2, 3])
Defensive patterns
Strategy: validation
Validate before calling
def make_text_part(text=None, tokens=None):
if text is None and tokens is None:
raise ValueError("skip: no content")
return TextPart(text=text, tokens=tokens) Type guard
from fish_speech.content_sequence import TextPart
def is_valid_text_part(d: dict) -> bool:
return d.get("type") == "text" and (d.get("text") is not None or d.get("tokens") is not None) Try / catch
try:
part = TextPart(**part_dict)
except ValueError as e:
logger.warning("skipping malformed text part: %s", e)
continue Prevention
- Never construct TextPart from unvalidated dicts; assert 'text' in d or 'tokens' in d first
- Log the offending part dict when validation fails so bad inputs are traceable
When it happens
Trigger: Constructing TextPart() or TextPart(text=None, tokens=None) without passing either field; or building a dict for ContentSequence(parts=[{"type": "text"}]) where neither key is set.
Common situations: Programmatically building parts lists where a text part dict is created but the text value was accidentally None (e.g. empty string from an upstream API became None), or copy-pasting a TextPart construction and deleting the payload.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Unsupported part type: {part['type']}
- Unsupported part type: {type(part)}
- Unsupported audio format: {audio_path.suffix}. Supported for
- {i} is not a file or directory
- Expected GenerateResponse, got {type(wrapped_result.response
AI-assisted analysis of fishaudio/fish-speech@befe400174 (2026-08-27).
Data as JSON: /api/errors/197ba72c6eb183e5.
Report an issue: GitHub.