{"record":{"id":"4a740f3f7878b4d1","repo":"calesthio/OpenMontage","slug":"kling-tts-result-path-data-task-result-audios-is-n","errorCode":null,"errorMessage":"Kling TTS result path data.task_result.audios is not a list","messagePattern":"Kling TTS result path data\\.task_result\\.audios is not a list","errorType":"exception","errorClass":"KlingAPIError","httpStatus":null,"severity":"error","filePath":"tools/audio/kling_tts.py","lineNumber":251,"sourceCode":"    ) -> tuple[str, list[dict[str, Any]]]:\n        \"\"\"Create a TTS task and return audio outputs.\n\n        Official TTS may return a completed task and task_result.audios[]\n        directly from POST /v1/audio/tts. Older/async behavior still requires\n        polling GET /v1/audio/tts/{task_id}, so support both shapes.\n        \"\"\"\n        if hasattr(client, \"post\"):\n            data = client.post(request[\"path\"], request[\"payload\"])\n            payload = data.get(\"data\") or {}\n            task_id = payload.get(\"task_id\")\n            if not task_id:\n                raise KlingAPIError(f\"Kling TTS create response missing data.task_id: {data}\")\n\n            task_result = payload.get(\"task_result\") or {}\n            outputs = task_result.get(\"audios\")\n            if outputs is not None:\n                if not isinstance(outputs, list):\n                    raise KlingAPIError(\"Kling TTS result path data.task_result.audios is not a list\")\n                return str(task_id), outputs\n\n            status = payload.get(\"task_status\") or payload.get(\"status\")\n            if status == \"failed\":\n                message = payload.get(\"task_status_msg\") or payload.get(\"message\") or \"Kling TTS task failed\"\n                raise KlingAPIError(str(message), code=payload.get(\"task_status\"), response=data)\n\n            return str(task_id), client.poll_classic(\n                request[\"path\"],\n                str(task_id),\n                \"audios\",\n                timeout_seconds=int(inputs.get(\"timeout_seconds\", 300)),\n                poll_interval=float(inputs.get(\"poll_interval\", 3.0)),\n            )\n\n        task_id = client.create_classic_task(request[\"path\"], request[\"payload\"])\n        return task_id, client.poll_classic(\n            request[\"path\"],","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/audio/kling_tts.py#L233-L269","documentation":"Raised as KlingAPIError when the create response contains data.task_result.audios but it is not a JSON list. This is a defensive shape check: the code found the key but cannot iterate it (e.g. it arrived as a dict keyed by index, or a string).","triggerScenarios":"Kling returns audios as an object instead of an array, or as a serialized string; nonstandard response from an intermediate gateway re-encoding the payload.","commonSituations":"API envelope drift between classic and new protocol versions; a proxy transforming arrays; mock/stub responses in tests built with the wrong shape.","solutions":["Log the offending task_result to see the actual type","If the upstream shape legitimately changed, adapt: wrap dict values or json.loads strings before the check","For tests, fix the fixture to use a list of url-bearing objects"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_audio_list(outputs: Any) -> bool:\n    return isinstance(outputs, list)","tryCatchPattern":"try:\n    result = kling_tts_tool.execute(inputs)\nexcept KlingAPIError as e:\n    if \"audios is not a list\" in str(e):\n        # envelope drift: log and fall back to polling path\n        logger.warning(\"kling audios shape changed: %s\", e)\n        raise\n    raise","preventionTips":["Pin tests/fixtures to documented response schemas","Treat shape changes as upstream API drift — check release notes","Keep the defensive checks; adapt only after confirming the new shape"],"tags":["kling","tts","api-contract","type-mismatch"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}