calesthio/OpenMontage · error · ValueError

video_list items must be objects

Error message

video_list items must be objects

What it means

Raised by KlingOfficialVideo while normalizing video reference inputs: every entry in the `video_list` input array must be a dict (JSON object), not a string, number, or list. The tool iterates `inputs.get('video_list')` and calls `add_video(item, 'video_list')` which expects to read keys like `video_url` off each item. A non-dict item cannot be mapped to the Kling API payload, so validation fails fast before any network call.

Source

Thrown at tools/video/kling_official_video.py:587

            if item.get("refer_type"):
                record["refer_type"] = item["refer_type"]
            if "keep_original_sound" in item:
                value = item["keep_original_sound"]
                record["keep_original_sound"] = "yes" if value is True else "no" if value is False else value
            video_list.append(record)
            references_used.append(
                {
                    "kind": "video",
                    "source": video_url,
                    "source_type": source_type,
                    "refer_type": record.get("refer_type"),
                    "keep_original_sound": record.get("keep_original_sound"),
                }
            )

        for item in inputs.get("video_list") or []:
            if not isinstance(item, dict):
                raise ValueError("video_list items must be objects")
            add_video(item, "video_list")
        if inputs.get("reference_video_url"):
            add_video({"video_url": inputs["reference_video_url"]}, "reference_video_url")
        for url in inputs.get("video_urls") or []:
            add_video({"video_url": url}, "video_urls")
        return video_list, references_used

    def _download_videos(
        self,
        client: KlingClient,
        outputs: list[dict[str, Any]],
        inputs: dict[str, Any],
    ) -> list[Path]:
        if not outputs:
            raise ValueError("Kling video response contained no videos")
        base_path = Path(inputs.get("output_path", "kling_official_video.mp4"))
        paths: list[Path] = []
        for index, item in enumerate(outputs):

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Change each entry to an object with a `video_url` key: `video_list: [{"video_url": "https://..."}]`
  2. If you only have plain URLs, use the `video_urls` input instead — that loop wraps each string into `{"video_url": url}` for you
  3. For a single reference video, use `reference_video_url` (also auto-wrapped)
  4. Check the tool's input schema via the registry before calling

Example fix

// before
inputs = {"video_list": ["https://cdn.example.com/ref.mp4"]}
// after
inputs = {"video_urls": ["https://cdn.example.com/ref.mp4"]}
// or
inputs = {"video_list": [{"video_url": "https://cdn.example.com/ref.mp4"}]}
Defensive patterns

Strategy: validation

Validate before calling

def normalize_video_list(video_list):
    if video_list is None:
        return []
    if not isinstance(video_list, list):
        raise TypeError("video_list must be a list")
    out = []
    for item in video_list:
        if isinstance(item, str):
            out.append({"video_url": item})  # or just use video_urls input
        elif isinstance(item, dict):
            out.append(item)
        else:
            raise ValueError(f"video_list item must be dict or url string: {item!r}")
    return out

Type guard

def is_video_list_valid(items: object) -> bool:
    return isinstance(items, list) and all(isinstance(i, dict) for i in items)

Try / catch

try:
    result = kling.execute(inputs)
except ValueError as e:
    if "video_list items must be objects" in str(e):
        inputs["video_list"] = [{"video_url": u} if isinstance(u, str) else u for u in inputs["video_list"]]
        result = kling.execute(inputs)
    else:
        raise

Prevention

When it happens

Trigger: Calling kling_official_video with `video_list` as a list of URL strings (e.g. `video_list: ['https://...mp4']`) instead of `[{"video_url": "https://..."}]`; passing a JSON-decoded array whose items are scalars; feeding a single string instead of a list of objects.

Common situations: Developers coming from other OpenMontage video tools that accept `video_urls` (a plain list of URL strings — note this same tool also accepts that key at the loop right below) and assuming `video_list` follows the same shape; hand-writing JSON payloads; LLM-generated tool inputs guessing the schema.

Related errors


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