{"record":{"id":"f64235d11ed7a4bf","repo":"PaddlePaddle/PaddleOCR","slug":"fileurl-and-filepath-are-mutually-exclusive","errorCode":null,"errorMessage":"fileUrl and filePath are mutually exclusive.","messagePattern":"fileUrl and filePath are mutually exclusive\\.","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/client.ts","lineNumber":256,"sourceCode":"      if (error instanceof InvalidRequestError) {\n        throw error;\n      }\n      throw new FileNotFoundError(parent, { cause: error });\n    }\n    return target;\n  }\n\n  private async submit(\n    model: string,\n    task: Job[\"task\"],\n    req: { fileUrl?: string; filePath?: string; pageRanges?: string; batchId?: string; options?: object },\n    signal?: AbortSignal,\n  ): Promise<string> {\n    if (!req.fileUrl && !req.filePath) {\n      throw new InvalidRequestError(\"Either fileUrl or filePath is required.\");\n    }\n    if (req.fileUrl && req.filePath) {\n      throw new InvalidRequestError(\"fileUrl and filePath are mutually exclusive.\");\n    }\n\n    this.validateModelForTask(model, task);\n    const payload = req.options || {};\n\n    if (req.fileUrl) {\n      return this.http.submitUrl(model, req.fileUrl, payload, {\n        pageRanges: req.pageRanges,\n        batchId: req.batchId,\n        signal,\n      });\n    }\n    return this.http.submitFile(model, req.filePath!, payload, {\n      pageRanges: req.pageRanges,\n      batchId: req.batchId,\n      signal,\n    });\n  }","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/client.ts#L238-L274","documentation":"Raised as FileNotFoundError from submit_file in paddleocr/_api_client/_http.py:135 when the local file to upload does not exist (os.path.exists check). This is a plain builtin exception, not a PaddleOCRAPIError subclass — important when writing except clauses. It fires before any network activity, so it is purely a client-side path problem.","triggerScenarios":"client.submit_file(..., file_path=...) where file_path points to a nonexistent path: typo, relative path resolved against the wrong working directory, file deleted, or wrong container mount.","commonSituations":"Relative paths in scripts run from a different cwd; Docker containers where the file is not mounted; tempfile already cleaned up; case-sensitive filesystem mismatches; path built with wrong variables.","solutions":["Check the path: os.path.abspath(file_path) and confirm it exists in the environment that runs the code","Use absolute paths constructed from a known root (pathlib.Path(__file__).parent / 'file.pdf')","In Docker, verify the file is mounted/copied into the container","If the path comes from user input, validate existence early and surface a clear error"],"exampleFix":"# before\njob_id = client.submit_file(model, \"input/doc.pdf\", {})\n# after\nfrom pathlib import Path\npdf = Path(__file__).parent / \"input\" / \"doc.pdf\"\nif not pdf.is_file():\n    raise SystemExit(f\"Input file not found: {pdf}\")\njob_id = client.submit_file(model, str(pdf), {})","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef ensure_uploadable(path: str) -> str:\n    p = Path(path).expanduser().resolve()\n    if not p.is_file():\n        raise FileNotFoundError(f\"Upload file missing: {p}\")\n    return str(p)","typeGuard":null,"tryCatchPattern":"try:\n    job_id = client.submit_file(model, file_path, {})\nexcept FileNotFoundError:\n    # builtin exception, NOT a PaddleOCRAPIError — catch it separately\n    logger.error(\"Input file not found: %s\", file_path)\n    raise","preventionTips":["Always resolve upload paths to absolute paths before calling submit_file","Catch FileNotFoundError separately — it is not a PaddleOCRAPIError subclass","In containers, mount input files explicitly and log resolved paths"],"tags":["file","validation","client-side","path"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}