{"record":{"id":"d88733f72fa3fac0","repo":"iflytek/astron-agent","slug":"cannot-provide-both-fileurl-and-file-parameters","errorCode":null,"errorMessage":"Cannot provide both fileUrl and file parameters","messagePattern":"Cannot provide both fileUrl and file parameters","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/knowledge/service/impl/ragflow_strategy.py","lineNumber":195,"sourceCode":"        )\n        if effective_top_k and effective_top_k > 0:\n            results = results[:effective_top_k]\n\n        logger.info(\"Query completed, returning %d results\", len(results))\n        return {\"query\": query, \"count\": len(results), \"results\": results}\n\n    def _empty_query_result(self, query: str) -> Dict[str, Any]:\n        \"\"\"Unified empty-result format for query paths.\"\"\"\n        return {\"query\": query, \"count\": 0, \"results\": []}\n\n    def _validate_split_parameters(\n        self, fileUrl: Optional[str], file: Optional[Any]\n    ) -> None:\n        \"\"\"Validate split method parameters.\"\"\"\n        if not fileUrl and not file:\n            raise ValueError(\"Either fileUrl or file must be provided\")\n        if fileUrl and file:\n            raise ValueError(\"Cannot provide both fileUrl and file parameters\")\n\n    def _parse_form_data_parameters(\n        self,\n        lengthRange: Optional[List[int]],\n        separator: Optional[List[str]],\n        cutOff: Optional[List[str]],\n    ) -> tuple[Optional[List[int]], Optional[List[str]], Optional[List[str]]]:\n        \"\"\"Parse form-data parameters from JSON strings.\"\"\"\n        parsed_length_range = lengthRange\n        parsed_separator = separator\n        parsed_cut_off = cutOff\n\n        if isinstance(lengthRange, str):\n            try:\n                parsed_length_range = json.loads(lengthRange) if lengthRange else None\n            except (json.JSONDecodeError, TypeError):\n                parsed_length_range = None\n","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/knowledge/service/impl/ragflow_strategy.py#L177-L213","documentation":"Raised by _validate_split_parameters (core/knowledge/service/impl/ragflow_strategy.py:195) when split() receives both fileUrl and a file object. The two input sources are mutually exclusive: the strategy cannot decide which one to upload to RAGFlow, so it rejects the request up front.","triggerScenarios":"Calling strategy.split(fileUrl='https://...', **{'file': uploaded_file}); also when an API handler merges form fields and multipart file into the same kwargs dict, unintentionally setting both.","commonSituations":"A frontend 'upload or link' form where the user both picked a file and left a previously-typed URL in place; middleware that defaults fileUrl to a placeholder while also attaching the file; programmatic callers copying kwargs from another strategy that allows both.","solutions":["Send exactly one input — remove fileUrl if you have a file object, or drop the file if you intend to fetch from fileUrl.","In the API layer, clear/ignore fileUrl whenever a multipart file part is present before calling split().","In UI code, disable or clear the URL field once a file is selected (and vice versa)."],"exampleFix":"// before\nchunks = await strategy.split(fileUrl=url, **{\"file\": f})  # both set\n\n// after\nif f is not None:\n    chunks = await strategy.split(**{\"file\": f})\nelse:\n    chunks = await strategy.split(fileUrl=url)","handlingStrategy":"validation","validationCode":"def resolve_single_input(fileUrl, file):\n    if fileUrl and file:\n        raise ValueError(\"fileUrl and file are mutually exclusive\")\n    return file if file else fileUrl","typeGuard":"def exactly_one_input(fileUrl, file) -> bool:\n    return bool(bool(file) != bool(fileUrl))","tryCatchPattern":"try:\n    chunks = await strategy.split(fileUrl=fileUrl, **{\"file\": file})\nexcept ValueError as e if \"both\" in str(e):\n    # prefer the uploaded file, retry without URL\n    chunks = await strategy.split(**{\"file\": file})","preventionTips":["Clear fileUrl in the UI as soon as a file is selected.","In handlers, ignore the URL field when a multipart file part exists.","Document the mutually exclusive contract of split() in its docstring/schema.","Use a discriminated request model (oneOf file/url) at the API boundary."],"tags":["validation","mutually-exclusive","ragflow","split"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}