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
- Inspect the raw extractResult array contents
- If testing against a mock, make each element an object with at least a non-empty string jobId and a valid state
- Upgrade the SDK / check API changelog for batch response changes
- 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
- Make test doubles return object items, never bare id strings
- Contract-test the batch endpoint shape in CI
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
- File not found: ${path}
- Destination already exists: ${target}
- Token is required. Set PADDLEOCR_ACCESS_TOKEN or pass token
- Model ${model} is not a document parsing model.
- Destination parent must be a directory: ${parent}
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/c01d19612c7ed229.
Report an issue: GitHub.