{"record":{"id":"b0d2f47b9c6719de","repo":"PaddlePaddle/PaddleOCR","slug":"either-fileurl-or-filepath-is-required","errorCode":null,"errorMessage":"Either fileUrl or filePath is required.","messagePattern":"Either fileUrl or filePath is required\\.","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/client.ts","lineNumber":253,"sourceCode":"        throw new InvalidRequestError(`Destination parent must be a directory: ${parent}`);\n      }\n    } catch (error) {\n      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,","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/client.ts#L235-L271","documentation":"Raised as NetworkError from submit_url in paddleocr/_api_client/_http.py:122 when the POST to create a URL-based job fails at the connection layer (requests.ConnectionError): DNS resolution failure, refused connection, TLS handshake failure, or connection reset. The request never completed, so no job was created. Original exception is chained for diagnosis.","triggerScenarios":"client.submit_url(...) with no internet, wrong/unresolvable API hostname, blocked port, corporate firewall or proxy rejecting the API host, or TLS interception failure.","commonSituations":"Offline or restricted CI environments; typo in base URL; DNS problems; firewall/geo-blocking of the API domain; expired corporate proxy credentials.","solutions":["Verify network connectivity: curl the API base URL from the same machine/container","Check the configured base URL for typos and correct region","Configure proxy env vars (HTTPS_PROXY) if behind a corporate proxy, or bypass it","Verify DNS resolution (nslookup/getent hosts <api-host>)","Retry — transient resets and DNS blips often clear immediately"],"exampleFix":"# diagnose\nimport requests\nprint(requests.get(\"https://<api-base>/\", timeout=10).status_code)","handlingStrategy":"retry","validationCode":"# preflight connectivity before bulk runs\nimport requests\ntry:\n    requests.head(api_base_url, timeout=5)\nexcept requests.ConnectionError:\n    print(\"API host unreachable — fix network/proxy first\")","typeGuard":null,"tryCatchPattern":"from paddleocr._api_client.errors import NetworkError\ntry:\n    job_id = client.submit_url(model, file_url, {})\nexcept NetworkError as e:\n    logger.error(\"Cannot reach API: %s\", e)\n    raise","preventionTips":["Validate base URL and DNS resolution at app startup","Configure HTTPS_PROXY in corporate environments","Prefer submit_url retries over silent fallbacks so duplicates are visible"],"tags":["network","connection","submit","retryable"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}