calesthio/OpenMontage · error · ValueError

element_list must be a list of element ids or objects

Error message

element_list must be a list of element ids or objects

What it means

Raised by normalize_element_list() in tools/_kling/elements.py when element_list is truthy but not a Python list. The function accepts a list of element ids (ints/strings) or objects ({element_id} / {id}), but rejects any other type before iterating.

Source

Thrown at tools/_kling/elements.py:22

internal provider reference mechanism in Phase 2, not a registry capability.
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from .client import KlingClient


def normalize_element_list(element_list: Any | None) -> list[dict[str, int]]:
    """Normalize official Kling element references to element_list objects."""

    if not element_list:
        return []
    if not isinstance(element_list, list):
        raise ValueError("element_list must be a list of element ids or objects")

    normalized: list[dict[str, int]] = []
    for item in element_list:
        raw_id: Any
        if isinstance(item, dict):
            raw_id = item.get("element_id", item.get("id"))
        else:
            raw_id = item
        if raw_id is None:
            raise ValueError("each element_list item must include element_id")
        try:
            element_id = int(raw_id)
        except (TypeError, ValueError) as exc:
            raise ValueError(f"element_id must be an integer-compatible value: {raw_id!r}") from exc
        if element_id <= 0:
            raise ValueError("element_id must be positive")
        normalized.append({"element_id": element_id})
    return normalized

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Wrap the value in a list: pass [element_id] instead of element_id
  2. If the value arrives as a JSON string, json.loads() it before calling
  3. Coerce tuples/sets to list before passing

Example fix

// before
refs = normalize_element_list(element_id)          # bare int
refs = normalize_element_list('{"element_id": 1}')  # JSON string

// after
refs = normalize_element_list([element_id])
refs = normalize_element_list(json.loads('[{"element_id": 1}]'))
Defensive patterns

Strategy: type-guard

Validate before calling

import json

def coerce_element_list(value):
    if isinstance(value, str):
        value = json.loads(value)          # accept JSON strings
    if isinstance(value, (int, str)) or (isinstance(value, dict) and value):
        value = [value]                    # accept a single item
    return value if isinstance(value, list) else None  # None => caller should reject

Type guard

def is_valid_element_list(value) -> bool:
    return value is None or (isinstance(value, list) and len(value) > 0)

Try / catch

from tools._kling.elements import normalize_element_list

try:
    refs = normalize_element_list(raw_value)
except ValueError as e:
    raise ValueError(f'bad element_list {raw_value!r}: {e}') from e

Prevention

When it happens

Trigger: Passing a bare int or string id ('12345'), a single dict instead of a list of dicts, a comma-separated string ('1,2,3'), or a tuple/JSON string that was never parsed — any of these is truthy but fails isinstance(element_list, list).

Common situations: Caller forwards an LLM/tool-produced JSON string without json.loads; caller grabs one element id from a previous response and passes it directly; YAML/JSON config where a single item is written as a scalar instead of a one-element list.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/6d014d2587cf6fb6. Report an issue: GitHub.