crewAIInc/crewAI · error · PermanentUploadError

Video processing failed for {file.filename}

Error message

Video processing failed for {file.filename}

What it means

PermanentUploadError raised by the sync Gemini upload path when the uploaded file's content_type starts with video/ and wait_for_processing(file_id) returns False, i.e. Gemini's Files API did not finish (or failed) processing the video within the uploader's wait budget. It is a subclass of UploadError and PermanentFileError, signaling retrying the same upload will not help.

Source

Thrown at lib/crewai-files/src/crewai_files/uploaders/gemini.py:184

                content = file.read()
                file_data = io.BytesIO(content)
                file_data.name = file.filename

                logger.info(
                    f"Uploading file '{file.filename}' to Gemini ({len(content)} bytes)"
                )

                uploaded_file = client.files.upload(
                    file=file_data,
                    config={
                        "display_name": display_name,
                        "mime_type": file.content_type,
                    },
                )

            if file.content_type.startswith("video/"):
                if not self.wait_for_processing(uploaded_file.name):
                    raise PermanentUploadError(
                        f"Video processing failed for {file.filename}",
                        file_name=file.filename,
                    )

            expires_at = datetime.now(timezone.utc) + GEMINI_FILE_TTL

            logger.info(
                f"Uploaded to Gemini: {uploaded_file.name} (URI: {uploaded_file.uri})"
            )

            return UploadResult(
                file_id=uploaded_file.name,
                file_uri=uploaded_file.uri,
                content_type=file.content_type,
                expires_at=expires_at,
                provider=self.provider_name,
            )
        except ImportError:

View on GitHub (pinned to 754d7323be)

Solutions

  1. Retry once with a smaller/shorter or re-encoded (H.264 mp4) video; codec/size issues are the usual cause.
  2. Check the file state via client.files.get(file_id) to distinguish still-processing from FAILED before retrying.
  3. Raise the uploader's wait timeout/polling budget if videos are legitimately large and processing is just slow.
  4. Treat PermanentUploadError as non-retryable in generic retry logic and surface it to the user for re-encoding.

Example fix

# before
result = gemini_uploader.upload(video_file)  # PermanentUploadError on slow processing

# after
try:
    result = gemini_uploader.upload(video_file)
except PermanentUploadError:
    # re-encode or split the video, then retry once
    result = gemini_uploader.upload(reencode_h264(video_file))
Defensive patterns

Strategy: try-catch

Try / catch

from crewai_files.uploaders.exceptions import PermanentUploadError  # or processing.exceptions
try:
    result = gemini_uploader.upload(video_file)
except PermanentUploadError as e:
    # non-retryable: re-encode/downscale the video, then retry once manually
    logger.error("Gemini could not process %s", e)
    raise

Prevention

When it happens

Trigger: Uploading a video/* file (mp4, webm, etc.) where Gemini's server-side processing stays in the 'processing' state past the polling timeout, or transitions to FAILED, so wait_for_processing returns False.

Common situations: Large or long videos that exceed the default polling window; unusual codecs that Gemini cannot process; transient Google-side processing failures; uploading many videos in parallel slowing processing.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/101f2bed4c39f505. Report an issue: GitHub.