nexu-io/open-design · error · ValueError
avatarMode=mixed requires at least one upload path
Error message
avatarMode=mixed requires at least one upload path
What it means
Thrown at the end of build_spec() when avatarMode is 'mixed' but none of the resolved participants carry an uploadPath. Mixed mode's contract is that at least one participant uses an uploaded avatar while others may use presets; if all end up preset-based, the mode is wrong.
Source
Thrown at skills/chat-motion-overlay/scripts/build_chat_overlay_spec.py:214
side = message["side"] or participant["side"]
if side != participant["side"]:
raise ValueError(f"Participant {speaker} appears on both {participant['side']} and {side}; use one side per participant")
avatar_key = participant["avatarKey"]
if message["avatar"] and message["avatar"] != participant["avatarKey"] and not configured_participant(speaker, config).get("preset"):
raise ValueError(f"Participant {speaker} has conflicting transcript avatar hints: {participant['avatarKey']} and {message['avatar']}; set a config preset to override")
messages.append(
{
"id": f"msg-{index + 1}",
"speaker": speaker,
"text": message["text"].strip(),
"side": side,
"avatarKey": avatar_key,
"appearAt": start + index * gap,
"highlight": bool(message["highlight"]),
}
)
if config["avatarMode"] == "mixed" and not any(participant.get("uploadPath") for participant in participants.values()):
raise ValueError("avatarMode=mixed requires at least one upload path")
duration = start + max(len(messages) - 1, 0) * gap + int(meta["hold"])
runtime_output = DELIVERY_TO_OUTPUT[config["deliveryFormat"]]
scene_config = {key: value for key, value in config.items() if key != "participants"}
return {
"title": meta["title"],
"timestamp": meta["time"],
"durationInFrames": duration,
"timing": {"start": start, "gap": gap, "hold": int(meta["hold"])},
"sceneConfig": {**scene_config, "output": runtime_output},
"participants": list(participants.values()),
"messages": messages,
}
def slugify(text: str) -> str:
lowered = text.strip().lower()
return re.sub(r"[^a-z0-9\u4e00-\u9fff]+", "-", lowered).strip("-") or "speaker"
View on GitHub (pinned to 5be4028344)
Solutions
- Give at least one participant (that actually appears in the transcript) an 'uploadPath' pointing at an existing image.
- Switch avatarMode to 'preset' if no uploads are needed.
- Switch avatarMode to 'upload' if every participant should have an uploadPath.
Example fix
// before
{"avatarMode": "mixed", "participants": {"闺蜜": {"preset": "female-bunny-pink"}, "老婆": {"preset": "female-cat-orange"}}}
// after
{"avatarMode": "mixed", "participants": {"闺蜜": {"uploadPath": "/me.png"}, "老婆": {"preset": "female-cat-orange"}}} Defensive patterns
Strategy: validation
Validate before calling
def mixed_needs_an_upload(config, transcript_speakers):
if config.get("avatarMode") != "mixed":
return
has_upload = any(config.get("participants", {}).get(s, {}).get("uploadPath") for s in transcript_speakers)
if not has_upload:
raise ValueError("avatarMode=mixed requires at least one transcript speaker with uploadPath") Prevention
- Only choose 'mixed' when you genuinely mix presets and uploads.
- Ensure the upload-bearing participant actually appears in the transcript.
When it happens
Trigger: avatarMode='mixed' with a config where no participant has uploadPath, or where upload-bearing participants never appear in the transcript so they are never instantiated. The run_test_matrix.py case 'invalid_mixed_without_upload' reproduces this.
Common situations: Setting avatarMode='mixed' as a 'safe default' without actually supplying an upload; configuring an upload participant under a speaker name that is misspelled relative to the transcript; deleting the only upload participant but leaving the mode as mixed.
Related errors
- avatarMode=preset does not allow uploadPath for participant
- avatarMode=upload requires uploadPath for participant {speak
- Unsupported avatar key for participant {speaker}: {avatar_ke
- Configured uploadPath for participant {participant['name']}
- Participant {speaker} appears on both {participant['side']}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/83ea6c55417de225.
Report an issue: GitHub.