fishaudio/fish-speech · error · ValueError
Unsupported part type: {part['type']}
Error message
Unsupported part type: {part['type']} What it means
When a ContentSequence is constructed, any part given as a plain dict is converted to the appropriate part dataclass (VQPart, AudioPart, TextPart) based on its "type" key. If the dict's type is not one of these known types, the part cannot be mapped and a ValueError is raised.
Source
Thrown at fish_speech/content_sequence.py:105
self: "ContentSequence",
parts: list[BasePart | dict] | None = None,
modality: Literal["text", "voice", "interleave"] | None = None,
metadata: dict | None = None,
):
self.modality = modality
self.metadata = metadata or {}
fixed_parts = []
for part in parts or []:
if isinstance(part, dict):
if part["type"] == "vq":
part = VQPart(**part)
elif part["type"] == "audio":
part = AudioPart(**part)
elif part["type"] == "text":
part = TextPart(**part)
else:
raise ValueError(f"Unsupported part type: {part['type']}")
fixed_parts.append(part)
self.parts = fixed_parts
# If modality is specified, add it at the beginning if it's not already there
if self.modality and not (
len(self.parts) > 0
and isinstance(self.parts[0], dict) is False
and isinstance(self.parts[0], TextPart)
and self.parts[0].text is not None
and self.parts[0].text.startswith(MODALITY_TOKENS[self.modality])
):
modality_token = MODALITY_TOKENS[self.modality]
self.parts.insert(0, TextPart(text=modality_token))
def append(
self: "ContentSequence",
part_or_parts: Union[BasePart, List[BasePart]],View on GitHub (pinned to befe400174)
Solutions
- Check the accepted part types in content_sequence.py and fix the dict's type key (e.g. "vq", "audio", "text")
- If loading old serialized data, migrate/normalize the type field before constructing ContentSequence
- Pass part dataclass instances (VQPart/AudioPart/TextPart) instead of dicts to get type checking earlier
Example fix
# before
seq = ContentSequence(parts=[{"type": "image", "path": "x.png"}])
# after
seq = ContentSequence(parts=[{"type": "text", "text": "hello"}]) Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_PART_TYPES = {"vq", "audio", "text"}
parts = [p for p in raw_parts if p.get("type") in ALLOWED_PART_TYPES] if all(isinstance(p, dict) for p in raw_parts) else raw_parts
seq = ContentSequence(parts=parts) Type guard
def is_supported_part_dict(p) -> bool:
return isinstance(p, dict) and p.get("type") in {"vq", "audio", "text"} Try / catch
try:
seq = ContentSequence(parts=raw_parts)
except ValueError as e:
if "Unsupported part type" in str(e):
# filter or migrate bad dicts, then retry
...
raise Prevention
- Validate serialized parts against a schema before loading
- Pass dataclass instances instead of dicts where possible
When it happens
Trigger: Passing a dict part like {"type": "image", ...} or {"type": "vq_codes"} (misspelled) into ContentSequence(parts=[...]); any type key outside {vq, audio, text} (and whatever earlier branches accept).
Common situations: Loading serialized sequences from JSON where the schema changed between versions, typos in the type field, or hand-authored part dicts using wrong type names.
Related errors
- Either text or tokens must be provided
- 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/c0b32fb92264c191.
Report an issue: GitHub.