calesthio/OpenMontage · warning · ValueError
Could not find download URL on ESA detail page: {detail_url}
Error message
Could not find download URL on ESA detail page: {detail_url} What it means
ValueError raised by the ESA adapter's download() when the esa.int detail page yields neither a matching anchor href nor a <video><source src> / <source src> element. Like Dareful, ESA is scraped from HTML; the error means the expected download markup was absent — page template change, media served only via a player/CDN blob, or the asset moved.
Source
Thrown at tools/video/stock_sources/esa.py:181
href = a.get("href", "")
text = a.get_text(strip=True).lower()
if any(ext in href.lower() for ext in [".mp4", ".mov", ".webm"]):
download_url = href
break
if "download" in text and href:
download_url = href
break
# Check for video source tags
if not download_url:
for source in soup.select("video source[src], source[src]"):
src = source.get("src", "")
if src:
download_url = src
break
if not download_url:
raise ValueError(f"Could not find download URL on ESA detail page: {detail_url}")
if not download_url.startswith("http"):
download_url = f"https://www.esa.int{download_url}"
return self._stream_download(download_url, out_path)
except Exception as e:
raise RuntimeError(f"ESA download failed for {detail_url}: {e}") from e
def _stream_download(self, url: str, out_path: Path) -> Path:
import requests
with requests.get(
url, stream=True, timeout=180,
headers={"User-Agent": "OpenMontage/1.0"},
) as r:
r.raise_for_status()
with open(out_path, "wb") as f:View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Verify the detail_url still resolves to a single-asset page with a visible video element.
- Extract the direct media URL from the page's network tab in a browser and download it directly if the adapter's selectors miss.
- Update the CSS selectors in esa.py if the markup merely changed shape but media elements remain.
- Fall back to another stock source for that clip.
Example fix
# before
path = esa.download(candidate, out)
# after
try:
path = esa.download(candidate, out)
except (ValueError, RuntimeError):
path = get_source("archive_org").download(alternate_candidate, out) Defensive patterns
Strategy: fallback
Try / catch
try:
path = esa.download(candidate, out_path)
except (ValueError, RuntimeError) as e:
logger.warning("esa scrape failed: %s", e)
path = get_source("archive_org").download(alt_candidate, out_path) Prevention
- Expect agency-site scrapers to break on redesigns; isolate them behind a source interface with alternates.
- Capture direct media URLs when available and persist them for resumable downloads.
When it happens
Trigger: ESA.int redesigns their multimedia pages; the video is embedded via a JavaScript player with no static <source> tag; the detail_url points to a gallery index rather than a single asset; a cookie/consent wall returns different HTML.
Common situations: Public-agency sites (ESA) revamping CMS with no API stability guarantee; EU cookie-consent interstitials altering the served DOM; old cached URLs from previously built corpora.
Related errors
- Could not find download URL on Dareful page: {detail_url}
- ESA download failed for {detail_url}: {e}
- Candidate {candidate.clip_id} has no download_url
- Dareful download failed for {detail_url}: {e}
- Downloading Atlas Cloud output failed: {exc}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/6cb6d253d7c5d127.
Report an issue: GitHub.