calesthio/OpenMontage · error · KlingAPIError
Kling Classic create response missing data.task_id: {data}
Error message
Kling Classic create response missing data.task_id: {data} What it means
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.
Source
Thrown at tools/_kling/client.py:73
def get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
return self._request("get", path, params=params)
def download(self, url: str, output_path: Path, timeout: int = 180) -> Path:
output_path.parent.mkdir(parents=True, exist_ok=True)
response = self.session.get(url, timeout=timeout)
self._raise_for_http_error(response)
content = getattr(response, "content", None)
if content is None and hasattr(response, "iter_content"):
content = b"".join(chunk for chunk in response.iter_content(chunk_size=1024 * 128) if chunk)
output_path.write_bytes(content or b"")
return output_path
def create_classic_task(self, path: str, payload: dict[str, Any]) -> str:
data = self.post(path, payload)
task_id = ((data.get("data") or {}).get("task_id"))
if not task_id:
raise KlingAPIError(f"Kling Classic create response missing data.task_id: {data}")
return str(task_id)
def poll_classic(
self,
path: str,
task_id: str,
result_key: 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(f"{path.rstrip('/')}/{task_id}")
payload = data.get("data") or {}
status = payload.get("task_status") or payload.get("status")
if status == CLASSIC_SUCCESS_STATUS:
task_result = payload.get("task_result") or {}
outputs = task_result.get(result_key) or []View on GitHub (pinned to 95e1c3d0ab)
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
Example fix
# before
task_id = client.create_classic_task("/v1/videos/text2video", payload)
# after (surface the raw body to see why no id came back)
data = client.post("/v1/videos/text2video", payload)
print(data) # inspect code/message, then fix payload or account access
task_id = client.create_classic_task("/v1/videos/text2video", payload) Defensive patterns
Strategy: type-guard
Validate before calling
resp = client.post(path, payload)
task_id = (resp.get("data") or {}).get("task_id")
if not task_id:
# inspect body for a business error before retrying anything
raise SystemExit(f"no task_id in create response: {resp.get('code')}/{resp.get('message')}") Type guard
def has_classic_task_id(data: dict) -> bool:
return bool((data.get("data") or {}).get("task_id")) Try / catch
try:
task_id = client.create_classic_task(path, payload)
except KlingAPIError as e:
body = str(e)
if "missing data.task_id" in body:
# body embeds the full response — check code/message for quota/param errors
raise SystemExit(f"create rejected: {body}")
raise Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Kling result did not include a remote video URL for lip-sync
- Kling Turbo create response missing data.id: {data}
- Kling TTS create response missing data.task_id: {data}
- Kling TTS result path data.task_result.audios is not a list
- Kling TTS response item contained no downloadable URL: {item
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/399c29f06ce7d35e.
Report an issue: GitHub.