{"record":{"id":"00197dadfada6651","repo":"calesthio/OpenMontage","slug":"video-list-items-must-be-objects","errorCode":null,"errorMessage":"video_list items must be objects","messagePattern":"video_list items must be objects","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/video/kling_official_video.py","lineNumber":587,"sourceCode":"            if item.get(\"refer_type\"):\n                record[\"refer_type\"] = item[\"refer_type\"]\n            if \"keep_original_sound\" in item:\n                value = item[\"keep_original_sound\"]\n                record[\"keep_original_sound\"] = \"yes\" if value is True else \"no\" if value is False else value\n            video_list.append(record)\n            references_used.append(\n                {\n                    \"kind\": \"video\",\n                    \"source\": video_url,\n                    \"source_type\": source_type,\n                    \"refer_type\": record.get(\"refer_type\"),\n                    \"keep_original_sound\": record.get(\"keep_original_sound\"),\n                }\n            )\n\n        for item in inputs.get(\"video_list\") or []:\n            if not isinstance(item, dict):\n                raise ValueError(\"video_list items must be objects\")\n            add_video(item, \"video_list\")\n        if inputs.get(\"reference_video_url\"):\n            add_video({\"video_url\": inputs[\"reference_video_url\"]}, \"reference_video_url\")\n        for url in inputs.get(\"video_urls\") or []:\n            add_video({\"video_url\": url}, \"video_urls\")\n        return video_list, references_used\n\n    def _download_videos(\n        self,\n        client: KlingClient,\n        outputs: list[dict[str, Any]],\n        inputs: dict[str, Any],\n    ) -> list[Path]:\n        if not outputs:\n            raise ValueError(\"Kling video response contained no videos\")\n        base_path = Path(inputs.get(\"output_path\", \"kling_official_video.mp4\"))\n        paths: list[Path] = []\n        for index, item in enumerate(outputs):","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/kling_official_video.py#L569-L605","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change each entry to an object with a `video_url` key: `video_list: [{\"video_url\": \"https://...\"}]`","If you only have plain URLs, use the `video_urls` input instead — that loop wraps each string into `{\"video_url\": url}` for you","For a single reference video, use `reference_video_url` (also auto-wrapped)","Check the tool's input schema via the registry before calling"],"exampleFix":"// before\ninputs = {\"video_list\": [\"https://cdn.example.com/ref.mp4\"]}\n// after\ninputs = {\"video_urls\": [\"https://cdn.example.com/ref.mp4\"]}\n// or\ninputs = {\"video_list\": [{\"video_url\": \"https://cdn.example.com/ref.mp4\"}]}","handlingStrategy":"validation","validationCode":"def normalize_video_list(video_list):\n    if video_list is None:\n        return []\n    if not isinstance(video_list, list):\n        raise TypeError(\"video_list must be a list\")\n    out = []\n    for item in video_list:\n        if isinstance(item, str):\n            out.append({\"video_url\": item})  # or just use video_urls input\n        elif isinstance(item, dict):\n            out.append(item)\n        else:\n            raise ValueError(f\"video_list item must be dict or url string: {item!r}\")\n    return out","typeGuard":"def is_video_list_valid(items: object) -> bool:\n    return isinstance(items, list) and all(isinstance(i, dict) for i in items)","tryCatchPattern":"try:\n    result = kling.execute(inputs)\nexcept ValueError as e:\n    if \"video_list items must be objects\" in str(e):\n        inputs[\"video_list\"] = [{\"video_url\": u} if isinstance(u, str) else u for u in inputs[\"video_list\"]]\n        result = kling.execute(inputs)\n    else:\n        raise","preventionTips":["Prefer the video_urls (list of strings) or reference_video_url inputs — the tool wraps them into objects for you","Run dry_run/validate before execute when composing inputs programmatically","Keep a schema check in test fixtures that feeds kling_official_video inputs"],"tags":["kling","input-validation","video-generation","schema"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}