{"record":{"id":"ffc88096e0b62678","repo":"calesthio/OpenMontage","slug":"dareful-download-failed-for-detail-url-e","errorCode":null,"errorMessage":"Dareful download failed for {detail_url}: {e}","messagePattern":"Dareful download failed for (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"tools/video/stock_sources/dareful.py","lineNumber":173,"sourceCode":"\n            # Check video elements\n            if not download_url:\n                for source in soup.select(\"video source[src], video[src]\"):\n                    src = source.get(\"src\", \"\")\n                    if src:\n                        download_url = src\n                        break\n\n            if not download_url:\n                raise ValueError(f\"Could not find download URL on Dareful page: {detail_url}\")\n\n            if not download_url.startswith(\"http\"):\n                download_url = f\"{_BASE_URL}{download_url}\"\n\n            return self._stream_download(download_url, out_path)\n\n        except Exception as e:\n            raise RuntimeError(f\"Dareful download failed for {detail_url}: {e}\") from e\n\n    def _stream_download(self, url: str, out_path: Path) -> Path:\n        import requests\n\n        with requests.get(\n            url, stream=True, timeout=180,\n            headers={\"User-Agent\": \"OpenMontage/1.0\"},\n        ) as r:\n            r.raise_for_status()\n            with open(out_path, \"wb\") as f:\n                for chunk in r.iter_content(chunk_size=1 << 16):\n                    if chunk:\n                        f.write(chunk)\n        return out_path\n","sourceCodeStart":155,"sourceCodeEnd":188,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/stock_sources/dareful.py#L155-L188","documentation":"RuntimeError raised by the Dareful adapter's outer except block, wrapping any exception raised during download — including the 'Could not find download URL' ValueError (356), HTTP failures inside _stream_download (raise_for_status on 403/404/5xx), timeouts, or parsing errors. The original exception is chained via 'from e', so the '{e}' suffix preserves the root cause.","triggerScenarios":"Any of: selector miss on the detail page, expired/signed download URL returning 403, bot-detection 403 on the media host, requests.Timeout after 180s, or BeautifulSoup parse exceptions — all re-thrown under this unified message.","commonSituations":"Bulk corpus builds where a fraction of Dareful links have expired; UA-based blocking (mitigated by the adapter's OpenMontage/1.0 User-Agent, but aggressive edges still block); slow origin timing out mid-stream.","solutions":["Inspect the chained cause (raise's __cause__) to identify whether it was scraping, HTTP, or timeout.","Treat Dareful failures as per-clip, not fatal: catch, log, continue the batch, and backfill from another source.","For repeated 403s, fetch the file URL with a real browser session and download directly.","For timeouts on large clips, retry once — transient origin slowness is common."],"exampleFix":"# before\npaths = [dareful.download(c, out) for c in candidates]\n\n# after\npaths = []\nfor c in candidates:\n    try:\n        paths.append(dareful.download(c, out))\n    except RuntimeError as e:\n        logger.warning(\"dareful clip %s failed: %s\", c.clip_id, e.__cause__ or e)","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"for c in candidates:\n    try:\n        paths.append(dareful.download(c, out))\n    except RuntimeError as e:\n        logger.warning(\"dareful %s failed (%s), continuing\", c.clip_id, e.__cause__ or e)\n        continue","preventionTips":["Inspect __cause__ to tell scrape misses from HTTP/timeout failures.","Design corpus builders to tolerate per-clip failures and backfill later."],"tags":["stock-footage","dareful","download","error-wrapping"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}