crewAIInc/crewAI · error · ValueError
Unable to extract transcript from YouTube video {video_id}:
Error message
Unable to extract transcript from YouTube video {video_id}: {e!s} What it means
The video loader's outer catch-all ValueError wrapping every exception during transcript retrieval and metadata enrichment. Because it uses 'except Exception', it also swallows and re-wraps the loader's own 'No transcript available' raise (254) — check the message suffix or __cause__ to distinguish missing captions from genuine failures. Inner metadata enrichment failures (title/author via pytube) are deliberately ignored with a bare pass, so this error almost always comes from the transcript API call itself.
Source
Thrown at lib/crewai-tools/src/crewai_tools/rag/loaders/youtube_video_loader.py:94
yt = YouTube(video_url)
metadata["title"] = yt.title
metadata["author"] = yt.author
metadata["length_seconds"] = yt.length
metadata["description"] = (
yt.description[:500] if yt.description else None
)
if yt.title:
content = f"Title: {yt.title}\n\nAuthor: {yt.author or 'Unknown'}\n\nTranscript:\n{content}"
except Exception: # noqa: S110
pass
else:
raise ValueError(
f"No transcript available for YouTube video: {video_id}"
)
except Exception as e:
raise ValueError(
f"Unable to extract transcript from YouTube video {video_id}: {e!s}"
) from e
return LoaderResult(
content=content,
source=video_url,
metadata=metadata,
doc_id=self.generate_doc_id(source_ref=video_url, content=content),
)
@staticmethod
def _extract_video_id(url: str) -> str | None:
"""Extract video ID from various YouTube URL formats."""
patterns = [
r"(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/v\/)([^&\n?#]+)",
]
for pattern in patterns:View on GitHub (pinned to 754d7323be)
Solutions
- Inspect e.__cause__ / the message suffix to classify: 'No transcript available' = content issue (see 254); 'blocked' / RequestBlocked = IP rate-limit; other = network or version issue.
- Upgrade or pin youtube-transcript-api to a version compatible with the loader's usage: uv add 'youtube-transcript-api>=1.0'.
- If blocked, route requests through a proxy the transcript API supports, or reduce request frequency / add caching.
- Add retry with backoff for transient network errors before surfacing the failure.
Example fix
# before
try:
result = loader.load(src)
except ValueError as e:
raise # loses classification
# after
try:
result = loader.load(src)
except ValueError as e:
msg = str(e)
if "No transcript available" in msg:
skip(src)
elif "blocked" in msg.lower():
backoff_and_retry(src)
else:
raise Defensive patterns
Strategy: retry
Validate before calling
def classify_yt_failure(exc: ValueError) -> str:
msg = str(exc)
if "No transcript available" in msg:
return "no-captions"
if "blocked" in msg.lower() or "ip" in msg.lower():
return "rate-limited"
return "unknown" Try / catch
attempt = 0
while attempt < 3:
try:
result = yt_video_loader.load(src)
break
except ValueError as e:
kind = classify_yt_failure(e)
if kind == "rate-limited" and attempt < 2:
attempt += 1
time.sleep(2 ** attempt)
continue
if kind == "no-captions":
skip(src)
break
raise Prevention
- Classify the wrapped message/cause before deciding retry vs skip vs escalate.
- Cache transcripts by video ID to minimize request volume and IP-block risk.
- Keep youtube-transcript-api version-compatible with the loader's constructor usage.
When it happens
Trigger: youtube-transcript-api raising network errors, rate limiting / IP blocks from YouTube (common on datacenter IPs, 'requests to youtube... blocked' errors), or API version incompatibilities after youtube-transcript-api's 1.x redesign (e.g. YouTubeTranscriptApi() constructor vs old static .list usage). The wrapped 'No transcript available' case is the other major trigger.
Common situations: Server-side scraping at volume triggering YouTube IP blocks; upgrading youtube-transcript-api past a major version where the internal API changed; running from cloud VMs whose IP ranges are challenged; transient network outages.
Related errors
- No transcript available for YouTube video: {video_id}
- Error. A valid pyproject.toml file is required. Check that a
- Invalid JSON response from {oauth_endpoint}
- Failed to connect to enterprise URL: {e!s}
- Git fetch failed with exit code {result.returncode} for comm
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/3582a3b98bb2aac0.
Report an issue: GitHub.