nexu-io/open-design · error · ValueError
Participant {speaker} config must use uploadPath, not upload
Error message
Participant {speaker} config must use uploadPath, not uploadAsset What it means
Raised by validate_config during participant iteration when a participant config contains an `uploadAsset` key. The script intentionally rejects `uploadAsset` and requires the semantically correct `uploadPath` field instead. The guard fires regardless of avatarMode whenever uploadAsset is truthy, catching a renamed/deprecated field name.
Source
Thrown at skills/chat-motion-overlay/scripts/build_chat_overlay_spec.py:144
if config["deviceFrame"] not in ALLOWED_DEVICE_FRAMES:
raise ValueError(f"Unsupported deviceFrame: {config['deviceFrame']}")
if config["nicknameMode"] not in ALLOWED_NICKNAME_MODES:
raise ValueError(f"Unsupported nicknameMode: {config['nicknameMode']}")
if config["deliveryFormat"] not in ALLOWED_DELIVERY_FORMATS:
raise ValueError(f"Unsupported deliveryFormat: {config['deliveryFormat']}")
if config["container"] == "none" and config["deviceFrame"] == "iphone-dynamic-island":
raise ValueError("container=none does not support deviceFrame=iphone-dynamic-island; use deviceFrame=none or choose an app container")
for speaker, participant in config.get("participants", {}).items():
side = participant.get("side")
if side and side not in {"left", "right"}:
raise ValueError(f"Unsupported side for participant {speaker}: {side}")
preset_key = participant.get("preset")
if preset_key and preset_key not in PRESET_KEYS:
raise ValueError(f"Unsupported preset for participant {speaker}: {preset_key}")
upload_path = participant.get("uploadPath")
if participant.get("uploadAsset"):
raise ValueError(f"Participant {speaker} config must use uploadPath, not uploadAsset")
if config["avatarMode"] == "preset" and upload_path:
raise ValueError(f"avatarMode=preset does not allow uploadPath for participant {speaker}")
if config["avatarMode"] == "upload" and not upload_path:
raise ValueError(f"avatarMode=upload requires uploadPath for participant {speaker}")
def auto_avatar_for_participant(participant_index: int, used_avatar_keys: set[str]) -> str:
preferred = [*PRESET_KEYS[participant_index:], *PRESET_KEYS[:participant_index]]
for avatar_key in preferred:
if avatar_key not in used_avatar_keys:
return avatar_key
return PRESET_KEYS[participant_index % len(PRESET_KEYS)]
def configured_participant(speaker: str, config: dict) -> dict:
return config.get("participants", {}).get(speaker, {})
View on GitHub (pinned to 5be4028344)
Solutions
- Rename the field from `uploadAsset` to `uploadPath` in the participant config, keeping the same value (an absolute path to the avatar image).
- Ensure avatarMode is compatible: 'upload' requires uploadPath; 'preset' disallows it (see related errors).
- Search the config source for any lingering 'uploadAsset' references and replace them all.
- If generating config programmatically, update the schema/serialization to emit uploadPath.
Example fix
// before
{"avatarMode": "upload", "participants": {"Alice": {"uploadAsset": "/abs/avatar.png"}}}
# -> ValueError: Participant Alice config must use uploadPath, not uploadAsset
// after
{"avatarMode": "upload", "participants": {"Alice": {"uploadPath": "/abs/avatar.png"}}} Defensive patterns
Strategy: validation
Validate before calling
for speaker, participant in config.get("participants", {}).items():
if participant.get("uploadAsset"):
raise SystemExit(
f"Participant {speaker} uses uploadAsset, which is not supported. "
"Rename it to uploadPath (same value)."
) Try / catch
try:
validate_config(config)
except ValueError as exc:
raise SystemExit(f"Config error: {exc}") from exc Prevention
- Use 'uploadPath' (the current field name), never 'uploadAsset'.
- Migrate any legacy config files that still use uploadAsset.
- If generating config from a schema, update the schema/serialization to emit uploadPath.
- Add a one-time migration check that scans configs for deprecated field names.
When it happens
Trigger: User copies an old or external config that used `uploadAsset` (perhaps from an earlier API or a different tool), or guesses the field name from related 'asset' terminology in the codebase. Any truthy uploadAsset value triggers the error.
Common situations: Field rename from an earlier version where uploadAsset was valid; confusion with other parts of the system that use an 'asset' concept; documentation/example using the old name; auto-generated config emitting the wrong key.
Related errors
- Unsupported side for participant {speaker}: {side}
- Unsupported preset for participant {speaker}: {preset_key}
- Unsupported container: {config['container']}
- Unsupported avatarMode: {config['avatarMode']}
- Unsupported deviceFrame: {config['deviceFrame']}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/b9258838eee7f162.
Report an issue: GitHub.