{"record":{"id":"9b927ad60a9f668e","repo":"PaddlePaddle/PaddleOCR","slug":"destination-already-exists-target-9b927a","errorCode":null,"errorMessage":"Destination already exists: {target}","messagePattern":"Destination already exists: (.+?)","errorType":"validation","errorClass":"InvalidRequestError","httpStatus":null,"severity":"warning","filePath":"paddleocr/_api_client/_resources.py","lineNumber":155,"sourceCode":"    if not parent.is_dir():\n        raise InvalidRequestError(f\"Destination parent must be a directory: {parent}\")\n    return target\n\n\ndef _require_existing_directory(destination: str) -> Path:\n    dest_dir = Path(destination)\n    if not dest_dir.exists():\n        raise FileNotFoundError(destination)\n    if not dest_dir.is_dir():\n        raise InvalidRequestError(\n            f\"Destination must be an existing directory: {destination}\"\n        )\n    return dest_dir\n\n\ndef _require_writable_target(target: Path, overwrite: bool) -> None:\n    if target.exists() and not overwrite:\n        raise InvalidRequestError(f\"Destination already exists: {target}\")\n\n\ndef _atomic_write(target: Path, content: bytes, overwrite: bool) -> None:\n    fd, temp_path = tempfile.mkstemp(\n        prefix=f\".{target.name}.tmp-\",\n        dir=str(target.parent),\n    )\n    try:\n        with os.fdopen(fd, \"wb\") as temp_file:\n            temp_file.write(content)\n        if overwrite:\n            os.replace(temp_path, target)\n        else:\n            os.link(temp_path, target)\n            os.remove(temp_path)\n    except FileExistsError as e:\n        raise InvalidRequestError(f\"Destination already exists: {target}\") from e\n    finally:","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_resources.py#L137-L173","documentation":"InvalidRequestError raised by _require_writable_target when the computed target file already exists and overwrite=False (the default). It is the pre-flight refusal so save_resource does not clobber existing files; no network request has been made when it fires.","triggerScenarios":"save_resource called twice with the same destination file (or same destination directory + URL basename) without overwrite=True; re-running a download script whose outputs already exist; batch helpers re-saving pages from a repeated job into the same output dir.","commonSituations":"Script reruns after partial completion; resumed pipelines re-downloading the same result artifacts; concurrent workers writing to one shared output dir with identical derived filenames.","solutions":["Pass overwrite=True when re-downloading is acceptable","Skip existing files at the call site if resume semantics are wanted","Derive unique filenames per run (job id, timestamp) to avoid collisions"],"exampleFix":"# before\nsave_resource(url, dest)  # rerun -> Destination already exists\n\n# after\nsave_resource(url, dest, overwrite=True)\n# or: if not Path(dest).exists(): save_resource(url, dest)","handlingStrategy":"validation","validationCode":"from pathlib import Path\nif Path(target_path).exists() and not overwrite:\n    return target_path  # resume: skip already-downloaded files","typeGuard":null,"tryCatchPattern":"try:\n    save_resource(url, dest)\nexcept InvalidRequestError as e:\n    if 'already exists' not in str(e):\n        raise\n    logger.info('skipping existing %s', dest)","preventionTips":["Make reruns idempotent: skip existing files at the call site for resume semantics","Pass overwrite=True deliberately when freshness matters more than safety"],"tags":["filesystem","overwrite","download"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}