fishaudio/fish-speech · error · ValueError

Unsupported part type: {type(part)}

Error message

Unsupported part type: {type(part)}

What it means

ContentSequence.encode walks over self.parts and encodes each part (text parts are tokenized, VQ parts produce semantic tokens). If a part is neither a TextPart, VQPart, AudioPart, nor other handled isinstance branch, encode has no encoding strategy and raises ValueError naming the offending type.

Source

Thrown at fish_speech/content_sequence.py:214

                    tokens = tokenizer.encode(part.text, add_special_tokens=False)
                else:
                    tokens = part.tokens

                tokens = torch.tensor(tokens, dtype=torch.long)
            elif isinstance(part, VQPart):
                # Critical Optimization: Vectorized mapping
                # Instead of loop lookup: [tokenizer.semantic_id_to_token_id[i] for i in codes]
                # We use arithmetic offset: code + semantic_begin_id
                # This assumes semantic tokens are contiguous in the vocab (DualAR requirement)
                curr_codes = part.codes.clone().to(torch.int)

                # Use int64 (long) for token IDs to avoid overflow or type mismatch in embedding
                tokens = (curr_codes[0] + tokenizer.semantic_begin_id).to(torch.long)

                vq_parts.append(curr_codes)
                vq_require_losses.append(part.cal_loss)
            else:
                raise ValueError(f"Unsupported part type: {type(part)}")

            all_tokens.append(tokens)

            # Set masks for different part types
            if isinstance(part, VQPart):
                vq_masks.append(torch.ones_like(tokens, dtype=torch.bool))
                audio_masks.append(torch.zeros_like(tokens, dtype=torch.bool))
            elif isinstance(part, AudioPart):
                vq_masks.append(torch.zeros_like(tokens, dtype=torch.bool))
                audio_mask = torch.ones_like(tokens, dtype=torch.bool)
                audio_mask[0] = False  # Skip start token
                audio_mask[-1] = False  # Skip end token
                audio_masks.append(audio_mask)
            else:
                vq_masks.append(torch.zeros_like(tokens, dtype=torch.bool))
                audio_masks.append(torch.zeros_like(tokens, dtype=torch.bool))

            # Set labels based on whether we want to calculate loss for this part

View on GitHub (pinned to befe400174)

Solutions

  1. Ensure all parts are instances of the supported dataclasses (TextPart/VQPart/AudioPart) before calling encode
  2. Construct the sequence through ContentSequence(...) so dicts are normalized in __init__
  3. If you defined a custom part type, extend/patch encode() to handle it via isinstance dispatch

Example fix

# before
seq.parts.append({"type": "text", "text": "hi"})
seq.encode(...)

# after
seq.parts.append(TextPart(text="hi"))
seq.encode(...)
Defensive patterns

Strategy: type-guard

Validate before calling

from fish_speech.content_sequence import TextPart, VQPart, AudioPart
SUPPORTED = (TextPart, VQPart, AudioPart)
assert all(isinstance(p, SUPPORTED) for p in seq.parts), "unencoded part present"

Type guard

from fish_speech.content_sequence import TextPart, VQPart, AudioPart

def is_encodable(part) -> bool:
    return isinstance(part, (TextPart, VQPart, AudioPart))

Try / catch

try:
    encoded = seq.encode(...)
except ValueError as e:
    if "Unsupported part type" in str(e):
        bad = [p for p in seq.parts if not isinstance(p, (TextPart, VQPart, AudioPart))]
        raise RuntimeError(f"bad parts: {bad}") from e
    raise

Prevention

When it happens

Trigger: Calling ContentSequence.encode() (directly or via encode_for_inference/visualize) when parts contains a raw dict that wasn't normalized (constructed by bypassing __init__ fixes), a None, or a custom/BasePart subclass that encode() doesn't handle.

Common situations: Appending parts to an existing sequence's .parts list directly, subclassing BasePart without extending encode(), or storing plain dicts in parts after object creation.

Related errors


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