microsoft/VibeVoice · error · ValueError
JSON file must contain a list of speaker entries
Error message
JSON file must contain a list of speaker entries
What it means
When `text` points at a .json file, the processor expects a top-level JSON array of {'speaker': ..., 'text': ...} entries. If json.load succeeds but yields an object (dict), a string, a number, or null, this ValueError is raised — the file parsed fine but has the wrong shape.
Source
Thrown at vibevoice/processor/vibevoice_processor.py:526
return result
def _convert_json_to_script(self, json_file: str) -> str:
"""
Convert JSON format to script format.
Expected JSON format:
[
{"speaker": "1", "text": "Hello everyone..."},
{"speaker": "2", "text": "Great to be here..."}
]
"""
import json
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
if not isinstance(data, list):
raise ValueError("JSON file must contain a list of speaker entries")
script_lines = []
for item in data:
if not isinstance(item, dict):
logger.warning(f"Skipping non-dict entry: {item}")
continue
speaker = item.get('speaker')
text = item.get('text')
if speaker is None or text is None:
logger.warning(f"Skipping entry missing speaker or text: {item}")
continue
# Ensure speaker ID is valid
try:
speaker_id = int(speaker)
except (ValueError, TypeError):View on GitHub (pinned to 94da20d98b)
Solutions
- Rewrite the JSON to a top-level list: [{"speaker": "1", "text": "..."}, {"speaker": "2", "text": "..."}].
- If your file wraps entries under a key (e.g. 'segments'), extract that array into a new file or pass the inner list via a temp file.
- Convert JSON-lines exports to a single JSON array before feeding them in.
Example fix
// before: dialog.json
{"segments": [{"speaker": "1", "text": "Hi"}]}
// after: dialog.json
[{"speaker": "1", "text": "Hi"}] Defensive patterns
Strategy: validation
Validate before calling
import json
data = json.load(open(path))
if not isinstance(data, list):
for key in ('segments', 'utterances', 'data'): # common wrappers
if isinstance(data, dict) and isinstance(data.get(key), list):
data = data[key]; break
else:
raise ValueError('transcript JSON root must be a list of speaker entries') Type guard
def is_speaker_entry_list(data) -> bool:
return isinstance(data, list) and all(
isinstance(x, dict) and 'speaker' in x and 'text' in x for x in data) Try / catch
try:
enc = processor(text=json_path)
except ValueError as e:
if 'must contain a list' in str(e):
data = json.load(open(json_path))['segments'] # unwrap known container
json.dump(data, open(json_path, 'w'))
enc = processor(text=json_path)
else:
raise Prevention
- Validate the JSON root type right after json.load in your own loading code.
- Standardize transcript exports on the flat [{'speaker','text'}] schema.
- Watch for JSON-lines files; convert them to a single array first.
When it happens
Trigger: Passing a .json file whose root is a dict — e.g. {"segments": [...]} or a bare {'speaker': '1', 'text': 'hi'} entry instead of a list wrapping it; or a JSON-lines file (one object per line) which json.load reads as whatever the first scalar parses to.
Common situations: Datasets that wrap transcripts in a metadata object ({'utterances': [...]}); annotation tools exporting a single-session dict; users hand-editing the example format and dropping the outer brackets.
Related errors
- No valid entries found in JSON file
- No valid content found in text file
- Unsupported file format: {file_ext}. Supported formats: .wav
- Audio input is required for ASR processing
- Could not process input text: {text}
AI-assisted analysis of microsoft/VibeVoice@94da20d98b (2026-08-15).
Data as JSON: /api/errors/c6e431e53f31e71e.
Report an issue: GitHub.