{"record":{"id":"04384eb51a22ebc0","repo":"calesthio/OpenMontage","slug":"kling-classic-task-failed","errorCode":null,"errorMessage":"Kling Classic task failed","messagePattern":"Kling Classic task failed","errorType":"exception","errorClass":"KlingAPIError","httpStatus":null,"severity":"error","filePath":"tools/_kling/client.py","lineNumber":97,"sourceCode":"        task_id: str,\n        result_key: str,\n        timeout_seconds: int = 900,\n        poll_interval: float = 5.0,\n    ) -> list[dict[str, Any]]:\n        deadline = time.time() + timeout_seconds\n        while time.time() < deadline:\n            data = self.get(f\"{path.rstrip('/')}/{task_id}\")\n            payload = data.get(\"data\") or {}\n            status = payload.get(\"task_status\") or payload.get(\"status\")\n            if status == CLASSIC_SUCCESS_STATUS:\n                task_result = payload.get(\"task_result\") or {}\n                outputs = task_result.get(result_key) or []\n                if not isinstance(outputs, list):\n                    raise KlingAPIError(f\"Kling Classic result path data.task_result.{result_key} is not a list\")\n                return outputs\n            if status == CLASSIC_FAILURE_STATUS:\n                message = payload.get(\"task_status_msg\") or payload.get(\"message\") or \"Kling Classic task failed\"\n                raise KlingAPIError(str(message), code=payload.get(\"task_status\"), response=data)\n            if status not in CLASSIC_PENDING_STATUSES:\n                raise KlingAPIError(f\"Unexpected Kling Classic task status {status!r}\", response=data)\n            time.sleep(min(poll_interval, max(0.0, deadline - time.time())))\n        raise TimeoutError(f\"Kling Classic task {task_id} timed out after {timeout_seconds}s\")\n\n    def create_turbo(self, path: str, payload: dict[str, Any]) -> str:\n        data = self.post(path, payload)\n        task_id = ((data.get(\"data\") or {}).get(\"id\"))\n        if not task_id:\n            raise KlingAPIError(f\"Kling Turbo create response missing data.id: {data}\")\n        return str(task_id)\n\n    def poll_turbo(\n        self,\n        task_id: str,\n        timeout_seconds: int = 900,\n        poll_interval: float = 5.0,\n    ) -> list[dict[str, Any]]:","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_kling/client.py#L79-L115","documentation":"Raised when a Kling Classic (official Kling API) async task poll returns a terminal failure status (CLASSIC_FAILURE_STATUS). The message is taken from the API's task_status_msg or message field, defaulting to 'Kling Classic task failed' when the API returns neither. The full poll response is attached to the exception via the response kwarg for diagnostics.","triggerScenarios":"Calling poll_classic() after create_classic_task() and the task transitions to the failure status. The server-side generation failed: content moderation rejection, invalid generation parameters (e.g. unsupported duration/resolution combo), insufficient credits/quota, or upstream model error.","commonSituations":"Prompts with sensitive content rejected by Kling moderation; account out of credits mid-generation; passing a parameter combination the endpoint does not support (e.g. 10s duration on a model that only allows 5s); malformed image reference causing the render to fail server-side.","solutions":["Catch KlingAPIError and inspect error.response -> data.task_status_msg for the server's actual failure reason","Check account credits/quota on the Kling console and top up if exhausted","Soften or rewrite the prompt if the message indicates content moderation (e.g. 'sensitive content')","Verify the payload parameters (duration, aspect_ratio, mode) against the Kling docs for the specific endpoint","Retry once — transient upstream failures do occur; use is_retryable_kling_error to gate the retry"],"exampleFix":"// before\noutputs = client.poll_classic('/v1/videos/text2video', task_id, 'videos')\n\n// after\nfrom tools._kling.errors import KlingAPIError\ntry:\n    outputs = client.poll_classic('/v1/videos/text2video', task_id, 'videos')\nexcept KlingAPIError as e:\n    detail = (e.response or {}).get('data', {}).get('task_status_msg') if e.response else None\n    raise RuntimeError(f'generation failed: {detail or e}') from e","handlingStrategy":"try-catch","validationCode":"from tools._kling.errors import KlingAPIError, is_retryable_kling_error\n\n# no pre-API validation possible for server-side failure, but gate the retry:\ndef safe_poll(client, path, task_id, result_key):\n    try:\n        return client.poll_classic(path, task_id, result_key)\n    except KlingAPIError as e:\n        if is_retryable_kling_error(e):\n            return client.poll_classic(path, task_id, result_key)\n        raise","typeGuard":"def is_classic_failure(exc: Exception) -> bool:\n    return (\n        isinstance(exc, KlingAPIError)\n        and getattr(exc, 'response', None) is not None\n        and (exc.response.get('data') or {}).get('task_status') == 'failed'\n    )","tryCatchPattern":"try:\n    outputs = client.poll_classic(path, task_id, 'videos')\nexcept KlingAPIError as e:\n    detail = ((e.response or {}).get('data') or {}).get('task_status_msg', str(e))\n    logger.error('kling classic failed: %s (task %s)', detail, task_id)\n    raise","preventionTips":["Log task_status_msg from the exception response — it contains the real reason","Validate prompt/parameter combos against the endpoint docs before submitting","Monitor account credits before launching batch generations","Keep task_id around so failures can be cross-checked in the Kling console"],"tags":["kling","api","async-task","polling","generation-failed"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}