PaddlePaddle/PaddleOCR · error · InvalidRequestError

Destination already exists: ${target}

Error message

Destination already exists: ${target}

What it means

Thrown by parse_batch_status in paddleocr/_api_client/_core.py:207 when an extractResult entry is an object but its 'jobId' is not a non-empty string. Every batch item must carry a jobId so the SDK can track each job individually. A missing/empty/null jobId in any single item fails the whole batch parse. ResponseFormatError.

Source

Thrown at api_sdk/typescript/src/client.ts:205

    let destinationStat;
    try {
      destinationStat = await stat(destination);
    } catch {
      throw new FileNotFoundError(destination);
    }
    if (!destinationStat.isDirectory()) {
      throw new InvalidRequestError(`Destination must be an existing directory: ${destination}`);
    }
  }

  private async requireWritableTarget(target: string, options: SaveResourceOptions): Promise<void> {
    try {
      await stat(target);
    } catch {
      return;
    }
    if (!options.overwrite) {
      throw new InvalidRequestError(`Destination already exists: ${target}`);
    }
  }

  private requireUniqueTargets(targets: string[], options: SaveResourceOptions): void {
    if (options.overwrite) {
      return;
    }
    const seen = new Set<string>();
    for (const target of targets) {
      if (seen.has(target)) {
        throw new InvalidRequestError(`Destination already exists: ${target}`);
      }
      seen.add(target);
    }
  }

  private async resolveDestination(url: URL, destination: string, options: SaveResourceOptions): Promise<string> {
    let destinationStat;

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Dump the batch response and identify which item lacks jobId
  2. If those jobs were cancelled/deleted server-side, recreate the batch
  3. Upgrade the SDK in case item schema changed
  4. Fix mock servers to always include a non-empty string jobId per item
Defensive patterns

Strategy: type-guard

Type guard

def batch_items_have_job_ids(data: dict) -> bool:
    items = data.get("extractResult")
    return isinstance(items, list) and all(
        isinstance(i, dict) and isinstance(i.get("jobId"), str) and i["jobId"]
        for i in items
    )

Try / catch

from paddleocr._api_client.errors import ResponseFormatError
try:
    batch = client.get_batch_status(batch_id)
except ResponseFormatError as e:
    if "jobId" in str(e):
        logger.error("One batch item lacks jobId; batch=%s", batch_id)
    raise

Prevention

When it happens

Trigger: get_batch_status where any extractResult item lacks jobId, e.g. {"state": "running"} with no jobId, or jobId is null/empty/numeric.

Common situations: Server dropping jobId for failed or expunged jobs; schema drift; mock batch payloads missing required keys; proxy-modified JSON.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/728e4d380a67f029. Report an issue: GitHub.