PaddlePaddle/PaddleOCR · error · InvalidRequestError

Destination must be an existing directory: ${destination}

Error message

Destination must be an existing directory: ${destination}

What it means

Thrown by parse_batch_status in paddleocr/_api_client/_core.py:204 while iterating data.extractResult: an element of that list is not a JSON object. Each element must be an object describing one job (jobId, state, ...); a scalar/string/null element means the server returned a malformed batch listing. ResponseFormatError, raised during batch status parsing.

Source

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

  private collectMappedResourcePlans(resources: Record<string, string>): ResourceSavePlan[] {
    return Object.keys(resources)
      .sort()
      .map((key) => ({
        resourceUrl: resources[key],
        filename: safeMapKeyFilename(key),
      }));
  }

  private async requireExistingDirectory(destination: string): Promise<void> {
    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;
    }

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Inspect the raw extractResult array contents
  2. If testing against a mock, make each element an object with at least a non-empty string jobId and a valid state
  3. Upgrade the SDK / check API changelog for batch response changes
  4. Report to PaddleOCR with the raw payload if the production server is emitting non-object entries

Example fix

# mock fix
# before
{"extractResult": ["job-1", "job-2"]}
# after
{"extractResult": [{"jobId": "job-1", "state": "done"}, {"jobId": "job-2", "state": "pending"}]}
Defensive patterns

Strategy: type-guard

Type guard

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

Try / catch

from paddleocr._api_client.errors import ResponseFormatError
try:
    batch = client.get_batch_status(batch_id)
except ResponseFormatError:
    logger.exception("Batch listing malformed; dumping raw response")
    raise

Prevention

When it happens

Trigger: get_batch_status where extractResult is a list but contains non-dict entries, e.g. ["job-1", "job-2"] instead of [{"jobId": "job-1", ...}].

Common situations: Server bug or schema drift; a proxied/cached response from a different API version; hand-rolled mock server returning simplified batch payloads.

Related errors


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