crewAIInc/crewAI · error · ValueError
Invalid YouTube URL: {video_url}
Error message
Invalid YouTube URL: {video_url} What it means
ValueError from the video loader's _extract_video_id returning None — the URL does not contain a parseable YouTube video ID. The static helper matches the standard watch?v=, youtu.be/, /shorts/, and embed URL shapes; anything else (including channel URLs) yields None and trips this check before any network call.
Source
Thrown at lib/crewai-tools/src/crewai_tools/rag/loaders/youtube_video_loader.py:39
LoaderResult with transcript content
Raises:
ImportError: If required YouTube libraries aren't installed
ValueError: If the URL is not a valid YouTube video URL
"""
try:
from youtube_transcript_api import YouTubeTranscriptApi
except ImportError as e:
raise ImportError(
"YouTube support requires youtube-transcript-api. "
"Install with: uv add youtube-transcript-api"
) from e
video_url = source.source
video_id = self._extract_video_id(video_url)
if not video_id:
raise ValueError(f"Invalid YouTube URL: {video_url}")
metadata: dict[str, Any] = {
"source": video_url,
"video_id": video_id,
"data_type": "youtube_video",
}
try:
api = YouTubeTranscriptApi()
transcript_list = api.list(video_id)
try:
transcript = transcript_list.find_transcript(["en"])
except Exception:
try:
transcript = transcript_list.find_generated_transcript(["en"])
except Exception:
transcript = next(iter(transcript_list))View on GitHub (pinned to 754d7323be)
Solutions
- Use a canonical video URL: https://www.youtube.com/watch?v=VIDEOID or https://youtu.be/VIDEOID with an 11-character ID.
- For channels, switch to the YouTube channel loader.
- Pre-validate with your own extraction (e.g. regex for [\w-]{11} after v= or youtu.be/) before calling load.
- Log the exact URL received — invisible truncation or HTML entity encoding (& instead of &) is a frequent culprit.
Example fix
# before loader.load(SourceContent(path="https://www.youtube.com/@handle")) # not a video # after loader.load(SourceContent(path="https://www.youtube.com/watch?v=dQw4w9WgXcQ"))
Defensive patterns
Strategy: validation
Validate before calling
import re
VIDEO_ID = re.compile(r"(?:[?&]v=|youtu\.be/|/shorts/|/embed/)([A-Za-z0-9_-]{11})")
def extract_video_id(url: str) -> str | None:
m = VIDEO_ID.search(url)
return m.group(1) if m else None
def is_video_url(url: str) -> bool:
return extract_video_id(url) is not None Try / catch
try:
result = yt_video_loader.load(src)
except ValueError as e:
if "Invalid YouTube URL" in str(e):
log.warning("unparseable youtube url: %r", url)
skip(src)
raise Prevention
- Pre-extract the 11-char video ID yourself and rebuild a canonical watch URL.
- HTML-decode URLs (& -> &) before validation.
- Send channel-form URLs to the channel loader, not this one.
When it happens
Trigger: Passing a channel URL (youtube.com/@handle) or playlist URL to the video loader; URLs where the ID parameter is empty or truncated (watch?v=); youtu.be links with extra path segments; URLs with malformed query strings that defeat parsing.
Common situations: Mixing up the video and channel loaders; LLM-generated URLs that look plausible but have malformed query params; URLs copy-pasted with the v parameter dropped by a truncating chat client; shortened share links mangled by markdown formatting.
Related errors
- Invalid YouTube channel URL: {channel_url}
- Blocked unsafe {label}: {e}
- Blocked unsafe URL: {e}
- Client is not initialized
- Invalid data_type: '{raw_data_type}'. Valid values are: 'fil
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/20e92f47e25f9f82.
Report an issue: GitHub.