{"record":{"id":"a9e98c1219a24cf3","repo":"iflytek/astron-agent","slug":"ragflow-chunk-snapshot-did-not-stabilize-after-retries-doc","errorCode":null,"errorMessage":"RAGFlow chunk snapshot did not stabilize after retries: doc={doc_id}, visible={last_visible_count}, expected={expected_count}","messagePattern":"RAGFlow chunk snapshot did not stabilize after retries: doc=(.+?), visible=(.+?), expected=(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"core/knowledge/infra/ragflow/ragflow_utils.py","lineNumber":329,"sourceCode":"    @staticmethod\n    def _finalize_chunk_retrieval(\n        dataset_id: str,\n        doc_id: str,\n        *,\n        expected_count: Optional[int],\n        last_visible_count: int,\n        max_retries: int,\n    ) -> List[Dict[str, Any]]:\n        \"\"\"Return an empty snapshot or raise the final incomplete-state error.\"\"\"\n        if expected_count is not None and expected_count > last_visible_count:\n            raise RuntimeError(\n                \"RAGFlow chunk snapshot remained incomplete after retries: \"\n                f\"doc={doc_id}, visible={last_visible_count}, \"\n                f\"expected={expected_count}\"\n            )\n\n        if last_visible_count > 0:\n            raise RuntimeError(\n                \"RAGFlow chunk snapshot did not stabilize after retries: \"\n                f\"doc={doc_id}, visible={last_visible_count}, \"\n                f\"expected={expected_count}\"\n            )\n\n        logger.warning(\n            \"RAGFlow document returned zero chunks after retries: \"\n            \"dataset=%s doc=%s attempts=%d\",\n            dataset_id,\n            doc_id,\n            max_retries + 1,\n        )\n        return []\n\n    @staticmethod\n    async def get_document_chunks(\n        dataset_id: str, doc_id: str, max_retries: int = 15, retry_delay: float = 3.0\n    ) -> List[Dict[str, Any]]:","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/knowledge/infra/ragflow/ragflow_utils.py#L311-L347","documentation":"_finalize_chunk_retrieval raises this RuntimeError when the visible chunk count is positive and greater than expected_count (or otherwise keeps changing) after retries — i.e. the snapshot did not stabilize. It signals RAGFlow was still actively modifying the chunk set (re-parsing, re-chunking) during polling, so any snapshot taken would be inconsistent.","triggerScenarios":"Polling get_document_chunks while a document is being re-parsed or deleted-and-recreated; last_visible_count > 0 but never equals the expected snapshot size within the retry budget.","commonSituations":"Triggering a re-parse while a consumer reads chunks concurrently; RAGFlow background re-index jobs; two ingestion jobs racing on the same document id.","solutions":["Stop concurrent parse/re-parse jobs on the document before fetching its chunks","Serialize ingestion: only call get_document_chunks after the parse job fully completes","Increase max_retries/retry_delay to outlast background re-indexing","Check for duplicate ingestion pipelines writing to the same RAGFlow document"],"exampleFix":"// before\nawait reparse(doc_id)\nchunks = await get_document_chunks(ds, doc_id)\n// after\nawait reparse_and_wait_until_done(doc_id)\nchunks = await get_document_chunks(ds, doc_id, max_retries=10)","handlingStrategy":"retry","validationCode":"# ensure no parse job is running for this doc before reading\nstatus = await get_document_run_status(ds, doc_id)\nif status not in (\"DONE\", None):\n    raise RuntimeError(f\"doc {doc_id} is being modified (status={status}); retry later\")","typeGuard":null,"tryCatchPattern":"try:\n    chunks = await get_document_chunks(ds, doc_id)\nexcept RuntimeError as e:\n    if \"did not stabilize\" in str(e):\n        schedule_retry(doc_id, delay_minutes=5)\n        return None\n    raise","preventionTips":["Never re-parse a document while consumers are reading its chunks","Serialize ingestion and read operations per document (lock or queue)","Debounce rapid re-upload/re-parse requests for the same doc","Alert on repeated instability — usually a sign of concurrent writers"],"tags":["ragflow","race-condition","unstable-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}