calesthio/OpenMontage · error · KlingAPIError
Kling Turbo create response missing data.id: {data}
Error message
Kling Turbo create response missing data.id: {data} What it means
Raised when create_turbo() posts successfully (HTTP and business-error checks passed) but the response JSON has no data.id field. The client expects the Turbo task-creation response shape {data: {id: ...}} and refuses to proceed without it; the full response body is embedded in the message for diagnosis.
Source
Thrown at tools/_kling/client.py:107
if status == CLASSIC_SUCCESS_STATUS:
task_result = payload.get("task_result") or {}
outputs = task_result.get(result_key) or []
if not isinstance(outputs, list):
raise KlingAPIError(f"Kling Classic result path data.task_result.{result_key} is not a list")
return outputs
if status == CLASSIC_FAILURE_STATUS:
message = payload.get("task_status_msg") or payload.get("message") or "Kling Classic task failed"
raise KlingAPIError(str(message), code=payload.get("task_status"), response=data)
if status not in CLASSIC_PENDING_STATUSES:
raise KlingAPIError(f"Unexpected Kling Classic task status {status!r}", response=data)
time.sleep(min(poll_interval, max(0.0, deadline - time.time())))
raise TimeoutError(f"Kling Classic task {task_id} timed out after {timeout_seconds}s")
def create_turbo(self, path: str, payload: dict[str, Any]) -> str:
data = self.post(path, payload)
task_id = ((data.get("data") or {}).get("id"))
if not task_id:
raise KlingAPIError(f"Kling Turbo create response missing data.id: {data}")
return str(task_id)
def poll_turbo(
self,
task_id: str,
timeout_seconds: int = 900,
poll_interval: float = 5.0,
) -> list[dict[str, Any]]:
deadline = time.time() + timeout_seconds
while time.time() < deadline:
data = self.get("/tasks", params={"task_ids": task_id})
records = data.get("data") or []
if not records:
raise KlingAPIError(f"Kling Turbo poll response missing data[0]: {data}")
record = records[0]
status = record.get("status") or record.get("task_status")
if status == TURBO_SUCCESS_STATUS:
outputs = record.get("outputs") or []View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Read the embedded response JSON in the message — if it contains an error/message field, the gateway returned a soft error; address that root cause
- Verify the path argument matches the Turbo gateway's documented create endpoint
- Check KLING_API_BASE_URL / base_url points at the correct Turbo deployment
- If the gateway now returns data.task_id, normalize the parser to accept both keys
Example fix
// before
task_id = client.create_turbo('/v2/videos', payload)
// after (inspect response, then adjust key if gateway changed)
resp = client.post('/v2/videos', payload)
task_id = (resp.get('data') or {}).get('id') or (resp.get('data') or {}).get('task_id')
if not task_id:
raise RuntimeError(f'unexpected create response: {resp}') Defensive patterns
Strategy: try-catch
Validate before calling
def turbo_create_response_has_id(data: dict) -> bool:
return bool((data.get('data') or {}).get('id')) Type guard
def extract_turbo_task_id(data: dict) -> str | None:
d = data.get('data')
if isinstance(d, dict):
tid = d.get('id') or d.get('task_id')
if tid:
return str(tid)
return None Try / catch
try:
task_id = client.create_turbo(path, payload)
except KlingAPIError as e:
logger.error('turbo create rejected, body: %s', e.response)
raise Prevention
- Smoke-test the create path once after any gateway/base_url change
- Keep business-error detection in _raise_for_business_error aligned with the gateway's error envelope
- Log the full body — it usually contains the soft error the gateway returned
When it happens
Trigger: Calling create_turbo() with a wrong path for the deployed Turbo gateway; the Turbo endpoint returning a differently-shaped success payload (e.g. data.task_id instead of data.id); a gateway/proxy (HeyGen-style Turbo proxy) that swallows errors into a 200 response with an error object instead of a data object.
Common situations: Base URL misconfiguration via KLING_API_BASE_URL pointing at a different Turbo deployment; API contract change on the Turbo gateway; passing a payload the gateway rejects softly (200 + error body) instead of with an HTTP error status.
Related errors
- Kling Turbo result path data[0].outputs is not a list
- Kling Turbo poll response missing data[0]: {data}
- Kling Turbo task failed
- Unexpected Kling Turbo task status {status!r}
- Kling Turbo task {task_id} timed out after {timeout_seconds}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/4afc2503baf0fac4.
Report an issue: GitHub.