{"record":{"id":"a88c97b3bc5e6425","repo":"ATH-MaaS/Pixelle-Video","slug":"unknown-media-type-media-result-media-type","errorCode":null,"errorMessage":"Unknown media type: {media_result.media_type}","messagePattern":"Unknown media type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/frame_processor.py","lineNumber":278,"sourceCode":"            local_path = await self._download_media(\n                media_result.url,\n                frame.index,\n                config.task_id,\n                media_type=\"video\"\n            )\n            frame.video_path = local_path\n            \n            # Update duration from video if available\n            if media_result.duration:\n                frame.duration = media_result.duration\n                logger.debug(f\"  ✓ Video generated: {local_path} (duration: {frame.duration:.2f}s)\")\n            else:\n                # Get video duration from file\n                frame.duration = await self._get_video_duration(local_path)\n                logger.debug(f\"  ✓ Video generated: {local_path} (duration: {frame.duration:.2f}s)\")\n        \n        else:\n            raise ValueError(f\"Unknown media type: {media_result.media_type}\")\n\n    async def _prepare_api_video_inputs(\n        self,\n        frame: StoryboardFrame,\n        config: StoryboardConfig,\n        api_video_params: dict,\n    ) -> None:\n        \"\"\"Prepare provider-specific inputs for API video models.\"\"\"\n        from pixelle_video.utils.os_util import get_task_frame_path\n\n        if api_video_params.pop(\"use_narration_audio_as_driving_audio\", False):\n            api_video_params[\"audio_path\"] = frame.audio_path\n\n        if frame.image_path or api_video_params.get(\"first_clip_path\") or api_video_params.get(\"first_video_path\"):\n            return\n\n        first_frame_workflow = api_video_params.pop(\"first_frame_workflow\", None)\n        if not first_frame_workflow:","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/frame_processor.py#L260-L296","documentation":"In _step_generate_media, after media generation the code branches on media_result.media_type (expected 'image' or 'video'); anything else falls into the final else and raises ValueError. This is an internal contract check: MediaResult.media_type must hold a known media kind for the frame pipeline to know whether to measure duration and log accordingly.","triggerScenarios":"Calling the frame processor's pipeline (__call__ -> _step_generate_media) with a MediaResult whose media_type string is not exactly 'image' or 'video' — e.g. 'audio', 'Image' (case mismatch), an empty string, or a new upstream media kind added without updating this branch.","commonSituations":"Upstream API or provider enum changed/added a media type (e.g. 'audio' or 'tts') not handled here; manual construction of MediaResult in tests with a typo'd type; case-sensitive comparison against mixed-case input.","solutions":["Log/inspect media_result.media_type at the failure point and confirm it is exactly 'image' or 'video' (case-sensitive).","Normalize the value before the branch: media_type = media_result.media_type.strip().lower().","If a new media type is legitimately produced upstream, add an elif branch handling it (e.g. audio duration measurement) in _step_generate_media.","Add a validation/whitelist check on media_type when constructing MediaResult so bad values fail early."],"exampleFix":"// before\nelse:\n    raise ValueError(f\"Unknown media type: {media_result.media_type}\")\n\n// after\nmedia_type = (media_result.media_type or \"\").strip().lower()\nif media_type == \"image\":\n    ...\nelif media_type == \"video\":\n    ...\nelse:\n    raise ValueError(f\"Unknown media type: {media_result.media_type!r}\")","handlingStrategy":"validation","validationCode":"ALLOWED = {\"image\", \"video\"}\ndef check_media_type(media_result) -> str:\n    mt = (getattr(media_result, \"media_type\", \"\") or \"\").strip().lower()\n    if mt not in ALLOWED:\n        raise ValueError(f\"Unsupported media_type before pipeline: {media_result.media_type!r}\")\n    return mt\n\ncheck_media_type(media_result)  # call before processor pipeline","typeGuard":"def is_known_media_result(mt: object) -> bool:\n    return isinstance(mt, str) and mt.strip().lower() in {\"image\", \"video\"}","tryCatchPattern":"try:\n    await processor(storyboard, config)\nexcept ValueError as e:\n    if \"Unknown media type\" in str(e):\n        logger.error(\"media_type contract broken: %s\", e)\n        # fix/normalize storyboard or upgrade library\n    else:\n        raise","preventionTips":["Normalize media_type to lowercase at the boundary where MediaResult is created.","Use an enum/Literal type for media_type so invalid values cannot be constructed.","When upgrading providers, diff their returned media kinds against the processor's supported set."],"tags":["validation","enum","value-error","python"],"backgroundTag":"unknown-media-type","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}