calesthio/OpenMontage · error · RuntimeError
Kling result did not include a remote video URL for…
Error message
Kling result did not include a remote video URL for lip-sync input.
What it means
Raised by _first_remote_url when parsing a completed Kling video generation result. The helper looks for `remote_url` at the top level, then iterates `remote_outputs` for `url`/`video_url`/`resource_url` keys; if none is found it cannot build the input for the next pipeline stage (lip-sync needs a remote video URL) and raises. It almost always means the Kling API response schema changed or the result is structurally different from expected, not that generation failed.
Solutions
- Print the full result_data dict and locate where the URL now lives (commonly under data.task_result.works[].resource_url in Kling responses)
- Update _first_remote_url to also check the actual field path found in the response, or pass the tool's documented output accessor instead of raw data
- Ensure the upstream result comes from a genuinely completed task (status succeeded), not a pending one polled early
- If only local files exist, upload/serve the artifact and construct the lip-sync input from a hosted URL
Example fix
# before
for item in result_data.get("remote_outputs") or []:
url = item.get("url") or item.get("video_url") or item.get("resource_url")
# after (also accept Kling works[] shape)
for item in (result_data.get("remote_outputs")
or ((result_data.get("data") or {}).get("task_result") or {}).get("works")
or []):
url = item.get("url") or item.get("video_url") or item.get("resource_url") Defensive patterns
Strategy: type-guard
Validate before calling
def has_remote_url(result_data: dict) -> bool:
if result_data.get("remote_url"):
return True
return any(
isinstance(i, dict) and (i.get("url") or i.get("video_url") or i.get("resource_url"))
for i in result_data.get("remote_outputs") or []
)
if not has_remote_url(result_data):
raise SystemExit("no remote URL in result; inspect payload before lip-sync") Type guard
def extract_remote_url(result_data: dict) -> str | None:
if result_data.get("remote_url"):
return str(result_data["remote_url"])
for item in result_data.get("remote_outputs") or []:
if isinstance(item, dict):
u = item.get("url") or item.get("video_url") or item.get("resource_url")
if u:
return str(u)
return None Try / catch
url = extract_remote_url(result_data)
if url is None:
print(json.dumps(result_data, indent=2)) # schema drift diagnostics
raise SystemExit("kling result schema lacks a remote video URL") Prevention
- Log full result payloads once per schema change so drift is visible
- Prefer tool-level accessors over raw dict digging
- Only feed completed (status=succeeded) results into lip-sync
When it happens
Trigger: Running the avatar smoke suite (--live-avatar or the avatar stage of --live-full): a kling_official_video/avatar call succeeds, then _first_remote_url(result.data) is called to feed the video URL into kling_lip_sync, but the response dict contains neither remote_url nor a usable remote_outputs entry.
Common situations: Kling API schema drift (renamed output fields); the avatar tool returning only local file paths (already downloaded artifacts) with no remote references; a partially-truncated result dict logged from an earlier session being replayed; empty remote_outputs list on an asynchronous task queried too early.
Related errors
- Avatar smoke requires an existing narration file
- Kling Classic create response missing data.task_id
- Kling Classic result path data.task_result.
- Kling image response item contained no downloadable URL
- failed
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/7c0137fec389a569.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/kling_official_animated_explainer_e2e.py:470
"estimated_cost_usd": sum(
float(getattr(result, "cost_usd", 0) or 0)
for result in (image_result, video_result)
)
+ float(tts_data.get("estimated_cost_usd") or 0),
}
def _first_remote_url(result_data: dict[str, Any]) -> str:
direct = result_data.get("remote_url")
if direct:
return str(direct)
for item in result_data.get("remote_outputs") or []:
if not isinstance(item, dict):
continue
url = item.get("url") or item.get("video_url") or item.get("resource_url")
if url:
return str(url)
raise RuntimeError("Kling result did not include a remote video URL for lip-sync input.")
def _run_live_avatar_suite(
project_dir: Path,
*,
timeout_seconds: int,
poll_interval: float,
) -> dict[str, Any]:
image = registry.get("image_selector")
avatar = registry.get("kling_avatar")
lip_sync = registry.get("kling_lip_sync")
assert image and avatar and lip_sync
assets_dir = project_dir / "assets"
image_dir = assets_dir / "images"
video_dir = assets_dir / "video"
artifacts_dir = project_dir / "artifacts"
narration_path = assets_dir / "audio" / "narration.mp3"View on GitHub (pinned to 95e1c3d0ab)