PaddlePaddle/PaddleOCR · error · InvalidRequestError

Destination parent must be a directory: ${parent}

Error message

Destination parent must be a directory: ${parent}

What it means

Raised as ResponseFormatError by _response_json in paddleocr/_api_client/_http.py:62 when the body parses as JSON but the top-level value is not an object — e.g. a JSON array, string, number, or null. The API envelope must be an object ({code, msg, data}); anything else cannot be unwrapped. Distinguished from error 167 (unparseable body): here the JSON is valid but wrongly shaped.

Source

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

      }
      seen.add(target);
    }
  }

  private async resolveDestination(url: URL, destination: string, options: SaveResourceOptions): Promise<string> {
    let destinationStat;
    try {
      destinationStat = await stat(destination);
    } catch {
      destinationStat = undefined;
    }
    const target = destinationStat?.isDirectory() ? join(destination, safeUrlBasename(url)) : destination;
    await this.requireWritableTarget(target, options);
    const parent = dirname(target);
    try {
      const parentStat = await stat(parent);
      if (!parentStat.isDirectory()) {
        throw new InvalidRequestError(`Destination parent must be a directory: ${parent}`);
      }
    } catch (error) {
      if (error instanceof InvalidRequestError) {
        throw error;
      }
      throw new FileNotFoundError(parent, { cause: error });
    }
    return target;
  }

  private async submit(
    model: string,
    task: Job["task"],
    req: { fileUrl?: string; filePath?: string; pageRanges?: string; batchId?: string; options?: object },
    signal?: AbortSignal,
  ): Promise<string> {
    if (!req.fileUrl && !req.filePath) {
      throw new InvalidRequestError("Either fileUrl or filePath is required.");

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Inspect the parsed top-level type of the response body
  2. Check the request URL against current API docs — an array top-level usually means a different resource endpoint
  3. Fix mock servers/fixtures to return an object envelope
  4. Upgrade the SDK if the API envelope changed
Defensive patterns

Strategy: type-guard

Type guard

def is_json_object_body(response) -> bool:
    try:
        return isinstance(response.json(), dict)
    except ValueError:
        return False

Try / catch

from paddleocr._api_client.errors import ResponseFormatError
try:
    status = client.get_job_status(job_id)
except ResponseFormatError as e:
    if "must be a JSON object" in str(e):
        logger.error("API returned a non-object JSON top level; check endpoint/SDK versions")
        raise

Prevention

When it happens

Trigger: An endpoint returning a bare JSON array (e.g. a list of jobs) or a JSON string literal with 2xx status, on submit/status/batch calls routed through _response_json.

Common situations: Wrong endpoint or API version returning a different top-level shape; a mock server returning arrays; middleware wrapping/unwrapping payloads; test fixtures with incorrect structure.

Related errors


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