ATH-MaaS/Pixelle-Video · error · FileNotFoundError

Generated media file not found

Error message

Generated media file not found: {local_path}

What it means

_download_media resolves a generated media URL into a local path. When the URL uses the file:// scheme it strips the prefix and requires the local file to exist; if os.path.exists fails it raises FileNotFoundError. The upstream media generation step reported success, but its declared output artifact is absent on disk.

Solutions

  1. Check the exact path in the message (strip file://) with ls/stat; verify the generating step actually completed and wrote the file.
  2. Ensure the storage path is on a shared volume when generator and processor run in different containers/hosts — use object storage URLs (http) instead of file:// across machines.
  3. Confirm task_id/frame_index/path construction (get_task_frame_path) matches where the generator actually saved the file.
  4. Add retry/wait logic if the file may appear asynchronously, or fail the media step upstream if its output is missing.
  5. Re-run the generation step for the affected frame if the artifact was cleaned up.

Example fix

// before
local_path = url[7:]
if not os.path.exists(local_path):
    raise FileNotFoundError(f"Generated media file not found: {local_path}")

// after
local_path = url[7:]
for _ in range(5):
    if os.path.exists(local_path):
        break
    await asyncio.sleep(1)
else:
    raise FileNotFoundError(
        f"Generated media file not found after wait: {local_path} "
        f"(task_id={task_id}, frame={frame_index})"
    )
Defensive patterns

Strategy: validation

Validate before calling

import os
def ensure_local_media(url: str) -> str:
    if url.startswith("file://"):
        p = url[7:]
        if not os.path.exists(p):
            raise FileNotFoundError(f"pre-check failed, generated file absent: {p}")
        return p
    return url

ensure_local_media(media_result.url)  # before continuing the pipeline

Try / catch

try:
    local = await processor_step(frame)
except FileNotFoundError as e:
    logger.error("generated artifact missing: %s", e)
    # re-run generation for this frame or switch to shared/remote storage

Prevention

When it happens

Trigger: Calling the pipeline when a provider/task returns a file:// URL (e.g. from a local generation worker or mounted volume) whose path was deleted, never created, or written to a different host/container filesystem; also reachable from _prepare_api_video_inputs for API video inputs.

Common situations: Distributed runs where the generating worker's local disk is not shared with the processor; temp-directory cleanup removing the file before download; wrong task_id/paths baked into the returned URL; race where the file write has not been flushed.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30). Data as JSON: /api/errors/e9b432a9687a4a16. Report an issue: GitHub.

Appendix: source

Thrown at pixelle_video/services/frame_processor.py:479

            estimated_duration = file_size / 2000
            return max(1.0, estimated_duration)  # At least 1 second
    
    async def _download_media(
        self,
        url: str,
        frame_index: int,
        task_id: str,
        media_type: str
    ) -> str:
        """Download media (image or video) from URL to local file"""
        import os
        from pixelle_video.utils.os_util import get_task_frame_path
        output_path = get_task_frame_path(task_id, frame_index, media_type)

        if url.startswith("file://"):
            local_path = url[7:]
            if not os.path.exists(local_path):
                raise FileNotFoundError(f"Generated media file not found: {local_path}")
            return local_path

        if os.path.exists(url):
            return url
        
        timeout = httpx.Timeout(connect=10.0, read=60, write=60, pool=60)
        async with httpx.AsyncClient(timeout=timeout) as client:
            response = await client.get(url)
            response.raise_for_status()
            
            with open(output_path, 'wb') as f:
                f.write(response.content)
        
        return output_path
    
    async def _get_video_duration(self, video_path: str) -> float:
        """Get video duration in seconds"""
        try:

View on GitHub (pinned to 848b054e4f)