nexu-io/open-design · error · ValueError

Unsupported nicknameMode: {config['nicknameMode']}

Error message

Unsupported nicknameMode: {config['nicknameMode']}

What it means

Raised by validate_config when config['nicknameMode'] is not in ALLOWED_NICKNAME_MODES = {"hidden","first-message-only","always"}. Default is 'hidden'. Controls how often a speaker's nickname appears in the rendered chat.

Source

Thrown at skills/chat-motion-overlay/scripts/build_chat_overlay_spec.py:129

    config = json.loads(json.dumps(DEFAULT_CONFIG))
    if not path:
        validate_config(config)
        return config
    user = json.loads(Path(path).read_text(encoding="utf-8"))
    config.update(user)
    validate_config(config)
    return config


def validate_config(config: dict) -> None:
    if config["container"] not in ALLOWED_CONTAINERS:
        raise ValueError(f"Unsupported container: {config['container']}")
    if config["avatarMode"] not in ALLOWED_AVATAR_MODES:
        raise ValueError(f"Unsupported avatarMode: {config['avatarMode']}")
    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:

View on GitHub (pinned to 5be4028344)

Solutions

  1. Set nicknameMode to one of: hidden, first-message-only, always.
  2. Map intent: 'never show' -> hidden; 'show once at first message' -> first-message-only; 'show on every message' -> always.
  3. Use lowercase exact tokens.
  4. Pre-validate: `assert c['nicknameMode'] in {'hidden','first-message-only','always'}`.

Example fix

// before
{"nicknameMode": "once"}
# -> ValueError: Unsupported nicknameMode: once

// after
{"nicknameMode": "first-message-only"}
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_NICKNAME_MODES = {"hidden", "first-message-only", "always"}

if config["nicknameMode"] not in ALLOWED_NICKNAME_MODES:
    raise SystemExit(
        f"nicknameMode must be one of {sorted(ALLOWED_NICKNAME_MODES)}; "
        f"got {config['nicknameMode']!r}"
    )

Type guard

def is_nickname_mode(value) -> bool:
    return value in {"hidden", "first-message-only", "always"}

Try / catch

try:
    validate_config(config)
except ValueError as exc:
    raise SystemExit(f"Config error: {exc}") from exc

Prevention

When it happens

Trigger: User sets `"nicknameMode": "once"`, `"nicknameMode": "every"`, `"nicknameMode": "never"`, or `"nicknameMode": "on"`. None of these are recognized tokens.

Common situations: Natural-language guesses that don't match the enum; wanting 'show once' and trying 'once' instead of 'first-message-only'; wanting 'always visible' and trying 'always-show'; stale or copied config.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/c94795adaacdcc32. Report an issue: GitHub.