calesthio/OpenMontage · error · ValueError
Candidate {candidate.clip_id} has no download_url
Error message
Candidate {candidate.clip_id} has no download_url What it means
ValueError raised by the Archive.org adapter's download() when the Candidate object has a falsy download_url. Search results can reference items whose file list did not yield a direct downloadable URL; the adapter refuses to guess (Archive.org item pages are not direct media) and fails before opening the network stream.
Source
Thrown at tools/video/stock_sources/archive_org.py:191
for doc in docs:
cand = self._hydrate_candidate(doc, filters)
if cand is not None:
out.append(cand)
if out:
return out
return []
def download(self, candidate: Candidate, out_path: Path) -> Path:
"""Stream the candidate's file to `out_path`.
Same pattern as the Pexels adapter — no caching, corpus builder
decides.
"""
import requests # lazy
if not candidate.download_url:
raise ValueError(
f"Candidate {candidate.clip_id} has no download_url"
)
out_path = Path(out_path)
out_path.parent.mkdir(parents=True, exist_ok=True)
with requests.get(
candidate.download_url, stream=True, timeout=300
) as r:
r.raise_for_status()
with open(out_path, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
if chunk:
f.write(chunk)
return out_path
# ------------------------------------------------------------------
# InternalsView on GitHub (pinned to 95e1c3d0ab)
Solutions
- Re-run search to get fresh candidates with populated download_url instead of reusing stale ones.
- Filter candidates before download: skip any where not candidate.download_url.
- If building candidates manually, always set download_url from the Archive.org file metadata (e.g. the 'url' of an ident'd file).
Example fix
# before
for c in candidates:
path = source.download(c, out)
# after
for c in candidates:
if not c.download_url:
continue
path = source.download(c, out) Defensive patterns
Strategy: validation
Validate before calling
candidates = [c for c in candidates if getattr(c, "download_url", None)]
Type guard
def is_downloadable(candidate) -> bool:
return bool(getattr(candidate, "download_url", None)) Try / catch
try:
path = source.download(candidate, out_path)
except ValueError as e:
if "no download_url" in str(e):
continue # skip bad candidate in batch loop
raise Prevention
- Re-run search instead of reusing stale or hand-built candidates.
- Filter on download_url truthiness before any download loop.
When it happens
Trigger: A candidate produced by search whose download_url was never populated (metadata lacking a playable file), candidates constructed manually in tests/scripts with only clip_id set, or stale candidates serialized before a schema change that renamed the URL field.
Common situations: Pipeline code that reuses candidates across sessions after pickling; deserialized candidates from an older schema; Archive.org items with restricted or derivative-only files.
Related errors
- Could not find download URL on Dareful page: {detail_url}
- Dareful download failed for {detail_url}: {e}
- Could not find download URL on ESA detail page: {detail_url}
- ESA 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/365764d6da129143.
Report an issue: GitHub.