{"record":{"id":"2040a17e94091442","repo":"ATH-MaaS/Pixelle-Video","slug":"api-vlm-analysis-returned-empty-description","errorCode":null,"errorMessage":"API VLM analysis returned empty description","messagePattern":"API VLM analysis returned empty description","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/api_asset_analysis.py","lineNumber":172,"sourceCode":"\n        providers = self.config.get(\"api_providers\", {}) or {}\n        dashscope = providers.get(\"dashscope\", {}) or {}\n\n        client = VLM(\n            dashscope_api_key=dashscope.get(\"api_key\"),\n            dashscope_base_url=dashscope.get(\"base_url\"),\n        )\n        result = await asyncio.to_thread(\n            client.query,\n            prompt,\n            image_paths,\n            selected_model,\n            None,\n            video_paths,\n        )\n        description = str(result or \"\").strip()\n        if not description:\n            raise RuntimeError(\"API VLM analysis returned empty description\")\n        return description\n\n    def _get_asset_type(self, path: Path) -> str:\n        image_exts = {\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\"}\n        video_exts = {\".mp4\", \".mov\", \".avi\", \".mkv\", \".webm\"}\n        ext = path.suffix.lower()\n        if ext in image_exts:\n            return \"image\"\n        if ext in video_exts:\n            return \"video\"\n        return \"unknown\"\n","sourceCodeStart":154,"sourceCodeEnd":184,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/api_asset_analysis.py#L154-L184","documentation":"_query_vlm str()s the VLM client result and raises RuntimeError if the trimmed description is empty — the API returned None, an empty string, or whitespace, so there is nothing useful to feed downstream.","triggerScenarios":"The VLM API call completed but returned None/empty: model refused or produced no content for the prompt, API returned an empty completion, or result was not str-able to non-empty text.","commonSituations":"Prompt/safety filtering on the provider side; rate-limited or degraded API returning empty bodies; wrong model chosen that doesn't support image/video input and yields empty output; transient provider outage.","solutions":["Retry the analysis — empty responses are often transient provider issues","Try a different/updated VLM model name supported by the provider","Check the provider logs/quota — safety filters or throttling often yield empty completions","Simplify the prompt passed to analyze_image/analyze_video"],"exampleFix":"# before\ndesc = await analyzer.analyze_image(path, model=\"some-vlm\")\n# after\ntry:\n    desc = await analyzer.analyze_image(path, model=\"some-vlm\")\nexcept RuntimeError:\n    desc = await analyzer.analyze_image(path, model=\"qwen-vl-max\")  # fallback model","handlingStrategy":"retry","validationCode":"# no pre-call validation possible; emptiness is only known after the API call","typeGuard":"def non_empty(value: object) -> bool:\n    return bool(str(value or \"\").strip())","tryCatchPattern":"for attempt in range(3):\n    try:\n        return await analyzer.analyze_image(path, model=model)\n    except RuntimeError as e:\n        if \"empty description\" not in str(e):\n            raise\n        await asyncio.sleep(2 ** attempt)\nraise RuntimeError(\"VLM returned empty description after retries\")","preventionTips":["Retry transient empty responses with backoff","Log the raw provider response to distinguish filtering vs outages","Fall back to an alternate VLM model when the primary returns empty"],"tags":["api","empty-response","vlm"],"backgroundTag":"empty-api-response","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}