{"record":{"id":"86e7cb5e9187dbf6","repo":"ArchiveBox/ArchiveBox","slug":"one-or-more-snapshot-tasks-failed","errorCode":null,"errorMessage":"One or more snapshot tasks failed","messagePattern":"One or more snapshot tasks failed","errorType":"exception","errorClass":"ExceptionGroup","httpStatus":null,"severity":"error","filePath":"archivebox/services/runner.py","lineNumber":449,"sourceCode":"                if task.done():\n                    if self.snapshot_tasks.get(snapshot_id) is task:\n                        self.snapshot_tasks.pop(snapshot_id, None)\n                    try:\n                        task.result()\n                    except asyncio.CancelledError as err:\n                        if _is_external_task_cancelled(err):\n                            raise\n                        stop_scheduling = True\n                    except Exception as err:\n                        task_errors.append(err)\n                        stop_scheduling = True\n                    continue\n                pending_tasks.append(task)\n            if not pending_tasks:\n                if task_errors:\n                    if len(task_errors) == 1:\n                        raise task_errors[0]\n                    raise ExceptionGroup(\"One or more snapshot tasks failed\", task_errors)\n                if stop_scheduling:\n                    return\n                await self.enqueue_pending_snapshots_from_projection()\n                if not self.snapshot_tasks:\n                    return\n                continue\n            await self.heartbeat_active_leases()\n            done, _pending = await asyncio.wait(pending_tasks, timeout=10.0, return_when=asyncio.FIRST_COMPLETED)\n            if not done:\n                continue\n            for task in done:\n                for snapshot_id, tracked_task in list(self.snapshot_tasks.items()):\n                    if tracked_task is task:\n                        self.snapshot_tasks.pop(snapshot_id, None)\n                        break\n                try:\n                    task.result()\n                except asyncio.CancelledError as err:","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/ArchiveBox/ArchiveBox/blob/74564b28220090664f919479e82cbf454125fa34/archivebox/services/runner.py#L431-L467","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ntry:\n    await runner.wait_for_snapshot_tasks()\nexcept Exception as e:\n    print(e)\n// after\ntry:\n    await runner.wait_for_snapshot_tasks()\nexcept* Exception as eg:\n    for sub in eg.exceptions:\n        log(sub)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await runner.wait_for_snapshot_tasks()\nexcept* Exception as eg:\n    for sub in eg.exceptions:\n        logger.error('snapshot task failed: %r', sub)\n# single-error case surfaces directly (not wrapped)","preventionTips":["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"],"tags":["asyncio","crawler","exception-group","snapshots"],"backgroundTag":"snapshot-task-failed","analyzedSha":"74564b28220090664f919479e82cbf454125fa34","analyzedAt":"2026-08-28T23:56:51.556Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}