nexu-io/open-design · error · ValueError

Unsupported message line shape: {line}

Error message

Unsupported message line shape: {line}

What it means

Raised by parse_message_line in build_chat_overlay_spec.py after the speaker:text regex fallback has been exhausted for '|' delimited lines. The function accepts specific shapes only: 2 parts (speaker|text or speaker|side with side lookup), 3 parts (speaker|side|text, speaker|text|highlight, or speaker|text|avatar), and 4+ parts where parts[1] is a valid side. Any other combination — e.g. 4+ parts where parts[1] is not a side — falls through to ValueError.

Source

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

    if len(parts) == 3:
        if is_flag(parts[2]):
            result["text"] = parts[1]
            result["highlight"] = True
            return result
        if is_side(parts[1]):
            result["side"] = SIDE_MAP[parts[1]]
            result["text"] = parts[2]
            return result
        result["text"] = parts[1]
        result["avatar"] = parts[2]
        return result
    if len(parts) >= 4 and is_side(parts[1]):
        result["side"] = SIDE_MAP[parts[1]]
        result["avatar"] = parts[2]
        result["text"] = parts[3]
        result["highlight"] = len(parts) > 4 and is_flag(parts[4])
        return result
    raise ValueError(f"Unsupported message line shape: {line}")


def is_side(value: str) -> bool:
    return value in SIDE_MAP


def is_flag(value: str) -> bool:
    return value.strip().lower() == "highlight"


def load_config(path: str | None) -> dict:
    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)

View on GitHub (pinned to 5be4028344)

Solutions

  1. For 4-field lines, use the supported order `Speaker | side | avatar | text` (plus optional `highlight` as 5th), where side is one of left/right/左/右.
  2. Drop extra '|' columns so the line collapses to 2 or 3 parts (the most permissive shapes).
  3. Verify each segment: side must be in {left,right,左,右}; a flag segment must be the literal 'highlight'.
  4. If you need richer per-message metadata, edit the transcript schema in the script rather than overloading the pipe format.

Example fix

// before
Alice | top-left | smile.png | hello
# -> ValueError: Unsupported message line shape: ...

// after (side must be a recognized token)
Alice | left | smile.png | hello
# or simpler:
Alice | hello
Defensive patterns

Strategy: validation

Validate before calling

SIDE_TOKENS = {"left", "right", "左", "右"}

def message_shape_ok(line: str) -> bool:
    if "|" not in line:
        return True  # handled by speaker:text regex path
    parts = [p.strip() for p in line.split("|")]
    if len(parts) == 2:
        return True
    if len(parts) == 3:
        return True
    if len(parts) >= 4 and parts[1] in SIDE_TOKENS:
        return True
    return False

bad = [ln for ln in lines if "|" in ln and not message_shape_ok(ln)]
if bad:
    raise SystemExit(f"Unsupported transcript shapes: {bad[:3]}")

Try / catch

try:
    parsed = parse_transcript(Path(args.input))
except ValueError as exc:
    raise SystemExit(f"Transcript parse error at line: {exc}") from exc

Prevention

When it happens

Trigger: A '|' delimited line whose segments do not fit any accepted shape: 4+ parts where the second segment is not a recognized side token (left/right/左/右), e.g. `Alice | extra | more | text`; or a line mixing avatar and side fields in an unsupported order.

Common situations: User invents an extended syntax (speaker|side|avatar|text|highlight) but puts fields in the wrong order; copy-paste from a spreadsheet adding extra columns; non-side value landing in the side slot; mixing the 3-part and 4-part grammars inconsistently within one transcript.

Related errors


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