{"record":{"id":"5cf0e8ba31bc26c9","repo":"iflytek/astron-agent","slug":"fetch-all-document-chunks-failed-on-page-page-for-doc","errorCode":null,"errorMessage":"fetch_all_document_chunks failed on page {page} for doc={document_id}: code={resp.get('code')}, message={resp.get('message')}","messagePattern":"fetch_all_document_chunks failed on page (.+?) for doc=(.+?): code=(.+?), message=(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"core/knowledge/infra/ragflow/ragflow_client.py","lineNumber":715,"sourceCode":"            chunk count.\n\n    Returns:\n        All chunks flattened into a single list (possibly empty).\n\n    Raises:\n        RuntimeError: on non-zero ``code`` from any paginated call, or when\n            ``max_pages`` is exceeded without ``total`` being reached.\n    \"\"\"\n    chunks: List[Dict[str, Any]] = []\n    # Optional so a page that drops ``total`` can't downgrade the stop condition.\n    total: Optional[int] = None\n    page = 1\n    while page <= max_pages:\n        resp = await list_document_chunks(\n            dataset_id, document_id, page=page, page_size=page_size\n        )\n        if resp.get(\"code\") != 0:\n            raise RuntimeError(\n                f\"fetch_all_document_chunks failed on page {page} for \"\n                f\"doc={document_id}: code={resp.get('code')}, \"\n                f\"message={resp.get('message')}\"\n            )\n        data = resp.get(\"data\") or {}\n        batch = data.get(\"chunks\") or []\n        chunks.extend(batch)\n        # Missing/None/non-int => keep last-known good value.\n        raw_total = data.get(\"total\")\n        if isinstance(raw_total, int) and raw_total >= 0:\n            total = raw_total\n        if total is not None and len(chunks) >= total:\n            return chunks\n        if not batch:\n            # Protocol anomaly (stale pagination, mid-request deletion, or\n            # server mis-report): fail closed to avoid re-inserting the\n            # missing chunks as if they didn't exist.\n            raise RuntimeError(","sourceCodeStart":697,"sourceCodeEnd":733,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/knowledge/infra/ragflow/ragflow_client.py#L697-L733","documentation":"fetch_all_document_chunks aborts when a page request to list document chunks returns a RAGFlow error code != 0. The error propagates the server's code and message so the caller knows pagination failed mid-way.","triggerScenarios":"RAGFlow returning code!=0 on GET /api/v1/datasets/{id}/documents/{doc_id}/chunks for any page: invalid dataset_id/document_id, expired/invalid API key, server-side error, or chunk index invalidated mid-pagination.","commonSituations":"Document deleted while paginating; dataset id typo'd or from a different tenant; RAGFlow server under load returning 5xx mapped into code; token/permission problems surfacing only on this endpoint.","solutions":["Validate dataset_id and document_id exist and belong to the tenant of the API key before paginating.","Retry the whole fetch (not per-page) with backoff if the failure is transient (5xx / server load).","Check RAGFlow server logs for the corresponding error code and message.","Refresh/regenerate the RAGFlow API key if the code indicates an auth problem."],"exampleFix":"# before: one long fetch, fails whole call\nchunks = await fetch_all_document_chunks(dataset_id, doc_id)\n# after: bounded retry on transient failure\nfor attempt in range(3):\n    try:\n        chunks = await fetch_all_document_chunks(dataset_id, doc_id)\n        break\n    except RuntimeError as e:\n        if attempt == 2:\n            raise\n        await asyncio.sleep(2 ** attempt)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    chunks = await fetch_all_document_chunks(dataset_id, document_id)\nexcept RuntimeError as e:\n    if \"failed on page\" in str(e):\n        logger.warning(f\"Transient chunk-page failure, retrying: {e}\")\n        await asyncio.sleep(2)\n        chunks = await fetch_all_document_chunks(dataset_id, document_id)\n    else:\n        raise","preventionTips":["Validate dataset_id/document_id and ownership before paginating","Apply bounded retries at the whole-fetch level, not per page","Monitor RAGFlow server health; alert on repeated non-zero codes"],"tags":["ragflow","pagination","api-error"],"backgroundTag":"api-error-response","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"}