{"record":{"id":"11a10458c2d9c8a4","repo":"iflytek/astron-agent","slug":"file-upload-failed-no-document-returned","errorCode":null,"errorMessage":"File upload failed: no document returned","messagePattern":"File upload failed: no document returned","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/knowledge/service/impl/ragflow_strategy.py","lineNumber":247,"sourceCode":"        \"\"\"Process document upload and return document ID.\"\"\"\n        file_content, filename = await RagflowUtils.process_file(file_input)\n        logger.info(\n            \"File processing completed: %s, size: %d bytes\",\n            filename,\n            len(file_content),\n        )\n\n        upload_response = await ragflow_client.upload_document_to_dataset(\n            dataset_id=dataset_id, file_content=file_content, filename=filename\n        )\n\n        if upload_response and len(upload_response) > 0:\n            doc_object = upload_response[0]\n            doc_id = doc_object.id\n            logger.info(\"Document uploaded successfully, ID: %s\", doc_id)\n            return doc_id\n        else:\n            raise ValueError(\"File upload failed: no document returned\")\n\n    async def _handle_document_parsing(\n        self, dataset_id: str, doc_id: str, parser_config: Dict[str, Any]\n    ) -> None:\n        \"\"\"Configure a document, trigger parsing, and wait for completion.\n\n        Only parser parameters are updated here. RAGFlow selects specialized\n        parsers for formats such as images, presentations, and email during\n        upload; forcing every document back to ``naive`` would either discard\n        that selection or make the update fail for visual documents.\n        \"\"\"\n        logger.info(\n            \"Configuring RAGFlow document parser: dataset=%s doc=%s \"\n            \"chunk_token_num=%s\",\n            dataset_id,\n            doc_id,\n            parser_config.get(\"chunk_token_num\"),\n        )","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/knowledge/service/impl/ragflow_strategy.py#L229-L265","documentation":"Raised in _process_document_upload (core/knowledge/service/impl/ragflow_strategy.py:247) when the RAGFlow upload endpoint responds successfully but the returned document list is empty, so no document id can be extracted. This means the upload call did not fail at transport level, yet RAGFlow did not register the document.","triggerScenarios":"ragflow_client.upload_document_to_dataset returns an empty list or None while HTTP status is 200 — e.g. the dataset_id does not exist (RAGFlow sometimes returns an empty data list instead of an error), the file content is empty, or the RAGFlow client SDK silently swallows a per-file failure and returns an empty batch result.","commonSituations":"Dataset deleted between resolution and upload (race condition); uploading a zero-byte or unreadable file; dataset id belongs to a different RAGFlow tenant so the server no-ops; RAGFlow SDK version where upload returns [] on quota exceeded without raising.","solutions":["Verify the dataset_id exists immediately before upload (GET /api/v1/datasets/{id}) and recreate it if missing.","Check the file being uploaded is non-empty and readable — log content length before calling upload.","Inspect the raw upload response in logs to see whether RAGFlow returned a per-file error code.","Confirm the RAGFlow instance/storage (MinIO/S3) is healthy and has free quota for new documents."],"exampleFix":"// before: upload with unverified dataset\ndoc_id = await strategy._process_document_upload(file, dataset_id)\n\n// after: guard before uploading\ninfo = await ragflow_client.get_dataset(dataset_id)\nif info is None:\n    dataset_id = await RagflowUtils.ensure_dataset(\"default\")\nif not file_content:\n    raise ValueError(\"Refusing to upload empty file\")\ndoc_id = await strategy._process_document_upload(file, dataset_id)","handlingStrategy":"validation","validationCode":"# pre-upload guards\ninfo = await ragflow_client.get_dataset(dataset_id)\nif info is None:\n    raise ValueError(f\"dataset {dataset_id} does not exist\")\nfile_content, filename = await RagflowUtils.process_file(file_input)\nif not file_content:\n    raise ValueError(f\"refusing to upload empty file {filename}\")","typeGuard":"def upload_response_has_doc(resp) -> bool:\n    return bool(resp) and hasattr(resp[0], \"id\")","tryCatchPattern":"try:\n    doc_id = await strategy._process_document_upload(file, dataset_id)\nexcept ValueError as e:\n    logger.error(\"upload produced no document for dataset=%s: %s\", dataset_id, e)\n    raise CustomException(CodeEnum.RAGFLOW_RAGError, str(e)) from e","preventionTips":["Re-verify dataset existence right before upload to avoid races.","Reject zero-byte or unreadable files before upload.","Confirm RAGFlow object storage (MinIO/S3) is healthy and has quota.","Log the raw upload response so empty-but-200 results are diagnosable."],"tags":["ragflow","upload","empty-response","document"],"backgroundTag":"empty-api-response","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}