{"record":{"id":"9ac429442d37de9f","repo":"calesthio/OpenMontage","slug":"conflicting-audio-input-in-face-choose-0-provide","errorCode":null,"errorMessage":"Conflicting audio input in face_choose[0]; provide audio_id or sound_file, not both","messagePattern":"Conflicting audio input in face_choose\\[0\\]; provide audio_id or sound_file, not both","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/avatar/kling_lip_sync.py","lineNumber":593,"sourceCode":"\n    @staticmethod\n    def _face_choose_result_metadata(\n        face_choose: list[dict[str, Any]],\n    ) -> list[dict[str, Any]]:\n        metadata: list[dict[str, Any]] = []\n        for item in face_choose:\n            record = {key: value for key, value in item.items() if key != \"sound_file\"}\n            if item.get(\"sound_file\"):\n                record[\"sound_file_provided\"] = True\n            metadata.append(record)\n        return metadata\n\n    @staticmethod\n    def _copy_audio_input(inputs: dict[str, Any], payload: dict[str, Any]) -> dict[str, Any]:\n        nested_audio_id = str(payload.get(\"audio_id\") or \"\").strip()\n        nested_sound_file = payload.get(\"sound_file\")\n        if nested_audio_id and nested_sound_file:\n            raise ValueError(\n                \"Conflicting audio input in face_choose[0]; provide audio_id or sound_file, not both\"\n            )\n\n        top_level_audio_id = str(inputs.get(\"audio_id\") or \"\").strip()\n        top_level_sound_requested = any(\n            inputs.get(key)\n            for key in (\"sound_file\", \"sound_file_url\", \"sound_file_path\", \"audio_path\")\n        )\n\n        if nested_audio_id:\n            if (\n                (top_level_audio_id and top_level_audio_id != nested_audio_id)\n                or top_level_sound_requested\n            ):\n                raise ValueError(\n                    \"Conflicting audio input between top-level fields and face_choose[0]\"\n                )\n            payload[\"audio_id\"] = nested_audio_id","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/avatar/kling_lip_sync.py#L575-L611","documentation":"Raised by KlingLipSyncTool._copy_audio_input when face_choose[0] contains both audio_id and sound_file. The Kling payload accepts exactly one audio source per face; supplying both an uploaded-audio reference and inline audio data is ambiguous, so the tool refuses before building the request.","triggerScenarios":"face_choose=[{'face_id': 'f1', 'audio_id': 'audio_123', 'sound_file': 'https://.../vo.mp3'}] on the advanced path. Either non-empty audio_id (after strip) together with a truthy sound_file triggers it.","commonSituations":"Migrating a payload from sound_file to a pre-uploaded audio_id and leaving the old field behind; agent templates merging every audio option into one dict.","solutions":["Delete one of the two fields from face_choose[0] — keep audio_id if you pre-uploaded the audio, otherwise keep sound_file","If you have a file, upload it first (or let the tool handle sound_file) and drop audio_id","Validate face_choose entries for mutual exclusivity of audio_id/sound_file before calling"],"exampleFix":"# before\nface = {\"face_id\": \"f1\", \"audio_id\": \"audio_123\", \"sound_file\": \"https://cdn/vo.mp3\"}\n\n# after\nface = {\"face_id\": \"f1\", \"sound_file\": \"https://cdn/vo.mp3\"}","handlingStrategy":"validation","validationCode":"face_item = (inputs.get(\"face_choose\") or [{}])[0]\nif str(face_item.get(\"audio_id\") or \"\").strip() and face_item.get(\"sound_file\"):\n    raise ValueError(\"face_choose[0] has both audio_id and sound_file\")","typeGuard":"def has_single_audio_source(face_item) -> bool:\n    return bool(str(face_item.get(\"audio_id\") or \"\").strip()) != bool(face_item.get(\"sound_file\"))","tryCatchPattern":null,"preventionTips":["Choose one audio representation per face: uploaded id or file/URL","When migrating fields, delete the old one","Validate mutual exclusivity before the call"],"tags":["kling","lip-sync","audio-input","conflicting-inputs"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}