crewAIInc/crewAI · error · ValueError
Failed to download PDF from {url}: {e!s}
Error message
Failed to download PDF from {url}: {e!s} What it means
Raised by PDFLoader._fetch_from_url() when anything fails while downloading a remote PDF: the bounded safe_get_bounded request (network error, HTTP error status after raise, exceeded max_bytes cap), or exceptions raised while returning the body. The broad except wraps it into ValueError with the URL and stringified cause.
Source
Thrown at lib/crewai-tools/src/crewai_tools/rag/loaders/pdf_loader.py:67
"""
headers = kwargs.get(
"headers",
{
"Accept": "application/pdf",
"User-Agent": "Mozilla/5.0 (compatible; crewai-tools PDFLoader)",
},
)
try:
body, _content_type, _final_url = safe_get_bounded(
url,
max_bytes=kwargs.get("max_bytes", DEFAULT_MAX_PDF_BYTES),
headers=headers,
timeout=30,
)
return body
except Exception as e:
raise ValueError(f"Failed to download PDF from {url}: {e!s}") from e
def load(self, source: SourceContent, **kwargs: Any) -> LoaderResult: # type: ignore[override]
"""Load and extract text from a PDF file or URL.
Args:
source: The source content containing the PDF file path or URL.
Returns:
LoaderResult with extracted text content.
Raises:
FileNotFoundError: If the PDF file doesn't exist.
ImportError: If required PDF libraries aren't installed.
ValueError: If the PDF cannot be read or downloaded.
"""
try:
import pymupdf # type: ignore[import-untyped]
except ImportError as e:View on GitHub (pinned to 754d7323be)
Solutions
- Verify the link with curl -I — confirm 200 and application/pdf; fix or re-generate the URL.
- For large PDFs, raise the cap: PDFLoader().load(src, max_bytes=50_000_000).
- Retry transient failures once; cache downloaded PDFs locally and pass the file path on subsequent runs.
- If the server blocks the default user-agent, download with your own session/headers and pass the local file.
Example fix
# before
result = PDFLoader().load(SourceContent('https://example.com/big-report.pdf')) # > max_bytes
# after
result = PDFLoader().load(
SourceContent('https://example.com/big-report.pdf'),
max_bytes=100 * 1024 * 1024,
) Defensive patterns
Strategy: retry
Validate before calling
import requests\n\ndef pdf_url_ok(url: str) -> bool:\n try:\n r = requests.head(url, timeout=10, allow_redirects=True)\n return r.ok and 'pdf' in r.headers.get('Content-Type', '')\n except requests.RequestException:\n return False Try / catch
try:\n result = PDFLoader().load(source)\nexcept ValueError as e:\n if 'Failed to download PDF' in str(e):\n result = cached_or_retry_later(source.source)\n else:\n raise
Prevention
- HEAD-check PDF links and their size before downloading.
- Pass max_bytes sized to your real documents.
- Cache downloads locally; re-run from the file path, not the URL.
When it happens
Trigger: PDFLoader().load(SourceContent('https://example.com/paper.pdf')) where the URL 404s, the host is unreachable/TLS fails, the download exceeds max_bytes (default DEFAULT_MAX_PDF_BYTES) and is aborted, or the request times out at 30s.
Common situations: Broken/expired links to PDFs; sites requiring cookies or blocking non-browser agents; very large PDFs exceeding the byte cap; flaky mobile/corporate networks; PDF URLs that actually return HTML (though that usually fails later at parse time).
Related errors
- Unable to fetch documentation from {docs_url}: {e}
- Error fetching content from URL {url}: {e!s}
- PDF support requires pymupdf. Install with: uv add pymupdf
- PDF file not found: {file_path}
- Error fetching content from URL {url}: {e!s}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/956818a06cd28499.
Report an issue: GitHub.