calesthio/OpenMontage · error · KlingAPIError
Unexpected Kling Turbo task status
Error message
Unexpected Kling Turbo task status {status!r} What it means
Raised when poll_turbo() sees a status that is neither TURBO_SUCCESS_STATUS, TURBO_FAILURE_STATUS, nor in TURBO_PENDING_STATUSES. Like the Classic variant, this guards against unknown status enum values from schema drift or unusual task lifecycle states, and carries the full response payload on the exception.
Solutions
- Log error.response to capture the exact status string and record shape
- Compare against current Turbo API docs and update TURBO_PENDING_STATUSES or add terminal-state handling in schemas.py
- If the status is terminal (cancelled/expired), surface it as a failure instead of polling forever
Example fix
// schemas.py — before
TURBO_PENDING_STATUSES = {'pending', 'running'}
// schemas.py — after (extend once the new status is confirmed non-terminal)
TURBO_PENDING_STATUSES = {'pending', 'running', 'queued'} Defensive patterns
Strategy: try-catch
Validate before calling
from tools._kling.schemas import TURBO_PENDING_STATUSES, TURBO_SUCCESS_STATUS, TURBO_FAILURE_STATUS
def classify_turbo_status(record: dict) -> str:
s = record.get('status') or record.get('task_status')
if s == TURBO_SUCCESS_STATUS: return 'success'
if s == TURBO_FAILURE_STATUS: return 'failure'
if s in TURBO_PENDING_STATUSES: return 'pending'
return 'unknown' Type guard
def turbo_status_is_handled(status: str) -> bool:
from tools._kling.schemas import TURBO_PENDING_STATUSES, TURBO_SUCCESS_STATUS, TURBO_FAILURE_STATUS
return status in (TURBO_PENDING_STATUSES | {TURBO_SUCCESS_STATUS, TURBO_FAILURE_STATUS}) Try / catch
try:
outputs = client.poll_turbo(task_id)
except KlingAPIError as e:
if 'Unexpected Kling Turbo task status' in str(e):
logger.error('unknown turbo status, response: %s', e.response)
raise Prevention
- Watch Turbo API changelogs for new status enum values
- Include cancelled/expired terminal states in your failure handling
- Log the raw record for any status your code does not recognize
When it happens
Trigger: The Turbo gateway introduces a new status (e.g. 'cancelled', 'expired', 'partial'); the task was cancelled via the console; record.get('status') is empty while task_status holds a value outside the known sets.
Common situations: Turbo API version updates adding lifecycle states; tasks cancelled or expiring between polls; aggregator gateways translating statuses into non-standard strings.
Related errors
- Unexpected Kling Classic task status
- Kling Turbo poll response missing data[0]
- Kling Turbo result path data[0].outputs is not a list
- Kling Turbo task timed out after s
- Kling Classic task failed
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/ee807657ea070cef.
Report an issue: GitHub.
Appendix: source
Thrown at tools/_kling/client.py:133
) -> 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 []
if not isinstance(outputs, list):
raise KlingAPIError("Kling Turbo result path data[0].outputs is not a list")
return outputs
if status == TURBO_FAILURE_STATUS:
message = record.get("message") or record.get("error") or "Kling Turbo task failed"
raise KlingAPIError(str(message), code=record.get("code"), request_id=record.get("request_id"), response=data)
if status not in TURBO_PENDING_STATUSES:
raise KlingAPIError(f"Unexpected Kling Turbo task status {status!r}", response=data)
time.sleep(min(poll_interval, max(0.0, deadline - time.time())))
raise TimeoutError(f"Kling Turbo task {task_id} timed out after {timeout_seconds}s")
def _request(self, method: str, path: str, **kwargs: Any) -> dict[str, Any]:
url = self._url(path)
last_error: KlingAPIError | None = None
for attempt in range(self.max_retries + 1):
try:
response = getattr(self.session, method)(url, headers=self.headers, timeout=30, **kwargs)
self._raise_for_http_error(response)
data = response.json()
self._raise_for_business_error(data)
return data
except KlingAPIError as error:
last_error = error
if attempt >= self.max_retries or not is_retryable_kling_error(error):
raise
time.sleep(min(2.0 * (attempt + 1), 8.0))View on GitHub (pinned to 95e1c3d0ab)