{"record":{"id":"399c29f06ce7d35e","repo":"calesthio/OpenMontage","slug":"kling-classic-create-response-missing-data-task-id","errorCode":null,"errorMessage":"Kling Classic create response missing data.task_id: {data}","messagePattern":"Kling Classic create response missing data\\.task_id: (.+?)","errorType":"exception","errorClass":"KlingAPIError","httpStatus":null,"severity":"error","filePath":"tools/_kling/client.py","lineNumber":73,"sourceCode":"\n    def get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:\n        return self._request(\"get\", path, params=params)\n\n    def download(self, url: str, output_path: Path, timeout: int = 180) -> Path:\n        output_path.parent.mkdir(parents=True, exist_ok=True)\n        response = self.session.get(url, timeout=timeout)\n        self._raise_for_http_error(response)\n        content = getattr(response, \"content\", None)\n        if content is None and hasattr(response, \"iter_content\"):\n            content = b\"\".join(chunk for chunk in response.iter_content(chunk_size=1024 * 128) if chunk)\n        output_path.write_bytes(content or b\"\")\n        return output_path\n\n    def create_classic_task(self, path: str, payload: dict[str, Any]) -> str:\n        data = self.post(path, payload)\n        task_id = ((data.get(\"data\") or {}).get(\"task_id\"))\n        if not task_id:\n            raise KlingAPIError(f\"Kling Classic create response missing data.task_id: {data}\")\n        return str(task_id)\n\n    def poll_classic(\n        self,\n        path: str,\n        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 []","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_kling/client.py#L55-L91","documentation":"KlingAPIError raised by create_classic_task when the POST succeeds (HTTP-level) but the response's data.task_id is missing/empty. The Kling 'classic' task-creation contract requires data.task_id as the handle for all subsequent polling; without it the task cannot be tracked. The entire response is embedded so you can see whether the server returned an error payload, a different schema, or a success shape without an id.","triggerScenarios":"Calling create_classic_task for image/video endpoints (e.g. /v1/images/generations, text-to-video classic routes) when the account lacks permission for the model, a param was invalid and Kling returned an error object instead of raising HTTP error status, or an API revision moved the id field (some routes use data.id for 'turbo' style).","commonSituations":"Free-tier key hitting an enterprise-only model (200-with-error-body responses are common on Chinese API gateways); endpoint path typo producing a different JSON shape; mixing classic vs turbo route conventions; base URL override pointing at a different regional deployment.","solutions":["Print the embedded response — if it contains code/message fields (e.g. 1002 invalid param, 3001 quota), fix that condition first","Confirm the model key in the payload is one your account can call and matches the endpoint's expected naming","Verify you're on the right endpoint family: create_turbo() expects data.id, create_classic_task() expects data.task_id — don't mix them","Check KLING_API_BASE_URL points at the correct official base if overridden"],"exampleFix":"# before\ntask_id = client.create_classic_task(\"/v1/videos/text2video\", payload)\n\n# after (surface the raw body to see why no id came back)\ndata = client.post(\"/v1/videos/text2video\", payload)\nprint(data)  # inspect code/message, then fix payload or account access\ntask_id = client.create_classic_task(\"/v1/videos/text2video\", payload)","handlingStrategy":"type-guard","validationCode":"resp = client.post(path, payload)\ntask_id = (resp.get(\"data\") or {}).get(\"task_id\")\nif not task_id:\n    # inspect body for a business error before retrying anything\n    raise SystemExit(f\"no task_id in create response: {resp.get('code')}/{resp.get('message')}\")","typeGuard":"def has_classic_task_id(data: dict) -> bool:\n    return bool((data.get(\"data\") or {}).get(\"task_id\"))","tryCatchPattern":"try:\n    task_id = client.create_classic_task(path, payload)\nexcept KlingAPIError as e:\n    body = str(e)\n    if \"missing data.task_id\" in body:\n        # body embeds the full response — check code/message for quota/param errors\n        raise SystemExit(f\"create rejected: {body}\")\n    raise","preventionTips":["Check the response's code/message fields whenever task_id is absent — Kling often returns 200 with an error body","Match endpoint family to parser: classic expects data.task_id, turbo expects data.id","Verify the model key is enabled for your account tier before creating tasks"],"tags":["kling","api-contract","task-creation","parsing"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}