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
- Retry once with a smaller/shorter or re-encoded (H.264 mp4) video; codec/size issues are the usual cause.
- Check the file state via client.files.get(file_id) to distinguish still-processing from FAILED before retrying.
- Raise the uploader's wait timeout/polling budget if videos are legitimately large and processing is just slow.
- 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
- Pre-validate videos: prefer H.264/mp4, reasonable size and duration.
- Give the uploader a generous processing-wait budget for large videos.
- Never blind-retry PermanentUploadError in generic backoff loops.
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
- google-genai is required for Gemini file uploads. Install wi
- Project name '{name}' would generate folder name '{folder_na
- Project name '{name}' contains no valid characters for a Pyt
- Gemini requires file_uri for FileReference
- Video '{filename}' duration ({duration:.1f}s) exceeds maximu
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/101f2bed4c39f505.
Report an issue: GitHub.