{"record":{"id":"53beb0104f0ad844","repo":"PaddlePaddle/PaddleOCR","slug":"destination-parent-must-be-a-directory-parent","errorCode":null,"errorMessage":"Destination parent must be a directory: ${parent}","messagePattern":"Destination parent must be a directory: (.+?)","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/client.ts","lineNumber":235,"sourceCode":"      }\n      seen.add(target);\n    }\n  }\n\n  private async resolveDestination(url: URL, destination: string, options: SaveResourceOptions): Promise<string> {\n    let destinationStat;\n    try {\n      destinationStat = await stat(destination);\n    } catch {\n      destinationStat = undefined;\n    }\n    const target = destinationStat?.isDirectory() ? join(destination, safeUrlBasename(url)) : destination;\n    await this.requireWritableTarget(target, options);\n    const parent = dirname(target);\n    try {\n      const parentStat = await stat(parent);\n      if (!parentStat.isDirectory()) {\n        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.\");","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/client.ts#L217-L253","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the parsed top-level type of the response body","Check the request URL against current API docs — an array top-level usually means a different resource endpoint","Fix mock servers/fixtures to return an object envelope","Upgrade the SDK if the API envelope changed"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_json_object_body(response) -> bool:\n    try:\n        return isinstance(response.json(), dict)\n    except ValueError:\n        return False","tryCatchPattern":"from paddleocr._api_client.errors import ResponseFormatError\ntry:\n    status = client.get_job_status(job_id)\nexcept ResponseFormatError as e:\n    if \"must be a JSON object\" in str(e):\n        logger.error(\"API returned a non-object JSON top level; check endpoint/SDK versions\")\n        raise","preventionTips":["Contract-test that API responses are object-shaped at the top level","Keep mock servers envelope-accurate"],"tags":["api","response-format","json","schema"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}