{"record":{"id":"ede7f5b0e033be59","repo":"ATH-MaaS/Pixelle-Video","slug":"video-analysis-failed-error-msg","errorCode":null,"errorMessage":"Video analysis failed: {error_msg}","messagePattern":"Video analysis failed: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/video_analysis.py","lineNumber":155,"sourceCode":"            kit = await self.core._get_or_create_comfykit()\n            \n            # Determine what to pass to ComfyKit based on source\n            if workflow_info[\"source\"] == \"runninghub\" and \"workflow_id\" in workflow_info:\n                # RunningHub: pass workflow_id\n                workflow_input = workflow_info[\"workflow_id\"]\n                logger.info(f\"Executing RunningHub workflow: {workflow_input}\")\n            else:\n                # Selfhost: pass file path\n                workflow_input = workflow_info[\"path\"]\n                logger.info(f\"Executing selfhost workflow: {workflow_input}\")\n            \n            result = await kit.execute(workflow_input, workflow_params)\n            \n            # 6. Extract description from result\n            if result.status != \"completed\":\n                error_msg = result.msg or \"Unknown error\"\n                logger.error(f\"Video analysis failed: {error_msg}\")\n                raise Exception(f\"Video analysis failed: {error_msg}\")\n            \n            # Extract text description from result\n            # Video understanding workflow returns text in result.texts array\n            description = None\n            \n            # Format 1: Direct texts array (most common for video understanding)\n            if result.texts and len(result.texts) > 0:\n                description = result.texts[0]\n                logger.debug(f\"Found description in result.texts: {description[:100]}...\")\n            \n            # Format 2: Selfhost outputs (direct text in outputs)\n            # Format: {'6': {'text': ['description text']}}\n            elif result.outputs:\n                for node_id, node_output in result.outputs.items():\n                    if 'text' in node_output:\n                        text_list = node_output['text']\n                        if text_list and len(text_list) > 0:\n                            description = text_list[0]","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/video_analysis.py#L137-L173","documentation":"After executing the video-understanding workflow via kit.execute, the analyzer checks result.status and raises a generic Exception if it is not \"completed\", carrying the workflow's own message. This surfaces upstream workflow/kit failures (API errors, content moderation, workflow misconfiguration) as a Python exception.","triggerScenarios":"kit.execute returns a result whose status != 'completed' with result.msg describing why — e.g. invalid API credentials for the workflow backend, workflow JSON resolving to a broken graph, input video rejected/too large, or the workflow runner timing out.","commonSituations":"Expired or missing workflow-service API keys; the analyse_video workflow JSON edited/broken; video exceeding platform limits (duration/size); transient service outages.","solutions":["Read error_msg in the exception — it is the workflow backend's own message","Verify workflow service credentials and that the workflow named by resolve_workflow_path loads correctly","Retry on transient statuses if the message indicates timeout/rate limits","Validate the video meets backend limits (size, duration, codec) before calling"],"exampleFix":"// before\nresult = await kit.execute(workflow_input, workflow_params)\ndescription = result.texts[0]  # may raise or be empty\n// after\nresult = await kit.execute(workflow_input, workflow_params)\nif result.status != 'completed':\n    logger.error(result.msg)\n    raise RuntimeError(f'workflow failed: {result.msg}')","handlingStrategy":"try-catch","validationCode":"def validate_workflow_inputs(video_path: str, workflow) -> None:\n    assert Path(video_path).is_file(), 'video must exist'\n    assert workflow is None or Path(workflow).is_file(), 'workflow json must exist'\n\n# plus pre-call credential check\nassert os.getenv('WORKFLOW_API_KEY'), 'workflow credentials missing'","typeGuard":null,"tryCatchPattern":"result = None\nfor attempt in range(3):\n    try:\n        description = await analyzer(video_path=vp)\n        break\n    except Exception as e:\n        logger.warning(f'analysis attempt {attempt} failed: {e}')\n        if attempt == 2:\n            raise","preventionTips":["Log result.status and result.msg on every workflow run","Health-check workflow service credentials before batch jobs","Validate videos against backend size/duration limits before submission"],"tags":["workflow","api","video-analysis","upstream-failure"],"backgroundTag":"workflow-execution-failed","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}