ArchiveBox/ArchiveBox · error · ExceptionGroup
One or more snapshot tasks failed
Error message
One or more snapshot tasks failed
What it means
wait_for_snapshot_tasks collects exceptions from concurrently running snapshot asyncio tasks; if all tasks finished and errors remain, it re-raises the single error directly, or wraps multiple in an ExceptionGroup with this message. It signals that one or more snapshots in the crawl failed rather than swallowing their errors.
Source
Thrown at archivebox/services/runner.py:449
if task.done():
if self.snapshot_tasks.get(snapshot_id) is task:
self.snapshot_tasks.pop(snapshot_id, None)
try:
task.result()
except asyncio.CancelledError as err:
if _is_external_task_cancelled(err):
raise
stop_scheduling = True
except Exception as err:
task_errors.append(err)
stop_scheduling = True
continue
pending_tasks.append(task)
if not pending_tasks:
if task_errors:
if len(task_errors) == 1:
raise task_errors[0]
raise ExceptionGroup("One or more snapshot tasks failed", task_errors)
if stop_scheduling:
return
await self.enqueue_pending_snapshots_from_projection()
if not self.snapshot_tasks:
return
continue
await self.heartbeat_active_leases()
done, _pending = await asyncio.wait(pending_tasks, timeout=10.0, return_when=asyncio.FIRST_COMPLETED)
if not done:
continue
for task in done:
for snapshot_id, tracked_task in list(self.snapshot_tasks.items()):
if tracked_task is task:
self.snapshot_tasks.pop(snapshot_id, None)
break
try:
task.result()
except asyncio.CancelledError as err:View on GitHub (pinned to 74564b2822)
Solutions
- Unwrap the ExceptionGroup and inspect each sub-exception (Python 3.11 except* or .exceptions) to find which snapshots failed
- Fix the underlying per-snapshot failures (plugin errors, network, DB) and re-run the crawl
- Enable verbose logging for the runner to get per-task stack traces before aggregation
Example fix
// before
try:
await runner.wait_for_snapshot_tasks()
except Exception as e:
print(e)
// after
try:
await runner.wait_for_snapshot_tasks()
except* Exception as eg:
for sub in eg.exceptions:
log(sub) Defensive patterns
Strategy: try-catch
Try / catch
try:
await runner.wait_for_snapshot_tasks()
except* Exception as eg:
for sub in eg.exceptions:
logger.error('snapshot task failed: %r', sub)
# single-error case surfaces directly (not wrapped) Prevention
- Add per-task exception logging inside snapshot coroutines
- Validate plugin/subprocess health before large crawls
- Use 'archivebox update' to retry only failed snapshots after fixing root cause
When it happens
Trigger: During a crawl (on_archivebox_CrawlStartEvent) snapshot tasks raise exceptions (plugin crashes, DB errors, subprocess failures); when no pending tasks remain, the aggregated errors are raised as an ExceptionGroup.
Common situations: Crawl 0.7+ runs where several extraction plugins fail; transient network failures across multiple snapshot tasks; inspecting why a crawl reported failure and needing to see all sub-errors.
Related errors
- Crawl setup hook {plugin.name}:{hook.name} did not start
- Crawl setup hook {plugin.name}:{hook.name} did not complete
- Snapshot events must be emitted from a CrawlStartEvent handl
- Snapshot {snapshot_id} did not complete
AI-assisted analysis of ArchiveBox/ArchiveBox@74564b2822 (2026-08-28).
Data as JSON: /api/errors/86e7cb5e9187dbf6.
Report an issue: GitHub.