{"record":{"id":"0bfee891f2dd1a29","repo":"PaddlePaddle/PaddleOCR","slug":"model-model-is-not-a-document-parsing-model","errorCode":null,"errorMessage":"Model ${model} is not a document parsing model.","messagePattern":"Model (.+?) is not a document parsing model\\.","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/client.ts","lineNumber":73,"sourceCode":"    const job = await this.submitOcr(req, options);\n    return this.waitOcrResult(job, options);\n  }\n\n  async parseDocument(req: DocParsingRequest, options?: { signal?: AbortSignal }): Promise<DocParsingResult> {\n    const job = await this.submitDocumentParsing(req, options);\n    return this.waitDocumentParsingResult(job, options);\n  }\n\n  async submitOcr(req: OCRRequest, options?: { signal?: AbortSignal }): Promise<Job> {\n    const model = req.model ?? Model.PPOCRv6;\n    const jobId = await this.submit(model, \"ocr\", req, options?.signal);\n    return { jobId, model, task: \"ocr\", pageRanges: req.pageRanges, batchId: req.batchId };\n  }\n\n  async submitDocumentParsing(req: DocParsingRequest, options?: { signal?: AbortSignal }): Promise<Job> {\n    const model = req.model ?? Model.PaddleOCRVL16;\n    if (!isDocumentParsingModel(model)) {\n      throw new InvalidRequestError(`Model ${model} is not a document parsing model.`);\n    }\n    const jobId = await this.submit(model, \"document_parsing\", req, options?.signal);\n    return { jobId, model, task: \"document_parsing\", pageRanges: req.pageRanges, batchId: req.batchId };\n  }\n\n  async waitOcrResult(job: Job | string, options?: { signal?: AbortSignal }): Promise<OCRResult> {\n    const resolved = this.resolveJob(job, \"ocr\");\n    const jsonlData = await this.poller.pollUntilDone(resolved.jobId, options?.signal);\n    return this.parseOCRResult(resolved.jobId, jsonlData);\n  }\n\n  async waitDocumentParsingResult(job: Job | string, options?: { signal?: AbortSignal }): Promise<DocParsingResult> {\n    const resolved = this.resolveJob(job, \"document_parsing\");\n    const jsonlData = await this.poller.pollUntilDone(resolved.jobId, options?.signal);\n    return this.parseDocParsingResult(resolved.jobId, jsonlData);\n  }\n\n  async getStatus(jobId: string, options?: { signal?: AbortSignal }): Promise<JobStatus> {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/client.ts#L55-L91","documentation":"Thrown by extract_job_id in paddleocr/_api_client/_core.py:177 when the unwrapped 'data' object of a job-submission response does not contain a non-empty string 'jobId'. After a successful submit, the SDK must extract jobId to poll the job; a missing, empty, or non-string jobId makes the response unusable. This is a ResponseFormatError, meaning the server broke the documented response schema.","triggerScenarios":"Calling client.submit_url() or client.submit_file() (or the async variants) where the 2xx response's data object lacks 'jobId' — e.g. data is {} or contains an id under a different key.","commonSituations":"API version drift renaming jobId; a mock/test server that returns a partial envelope; middleware stripping fields; hitting the wrong endpoint that returns a valid envelope with different content.","solutions":["Capture and inspect the full response body to confirm what keys 'data' actually contains","Verify the SDK version matches the API version you are calling (upgrade paddleocr)","If using a mock server in tests, make it return {\"code\":0, \"data\":{\"jobId\":\"<non-empty-string>\"}}","Check whether a proxy or gateway is truncating/modifying the response"],"exampleFix":"# mock/test server fix\n# before\n{\"code\": 0, \"data\": {\"id\": \"abc123\"}}\n# after\n{\"code\": 0, \"data\": {\"jobId\": \"abc123\"}}","handlingStrategy":"validation","validationCode":null,"typeGuard":"def has_job_id(data: dict) -> bool:\n    jid = data.get(\"jobId\")\n    return isinstance(jid, str) and bool(jid.strip())","tryCatchPattern":"from paddleocr._api_client.errors import ResponseFormatError\ntry:\n    job_id = client.submit_file(model, path, {})\nexcept ResponseFormatError as e:\n    if \"jobId\" in str(e):\n        logger.error(\"Submit response lacked jobId; dumping and retrying once\")\n        raise","preventionTips":["Keep mock servers schema-accurate: {code:0, data:{jobId:str}}","Persist returned jobIds immediately so submission anomalies are diagnosable","Upgrade SDK together with API changes"],"tags":["api","response-format","job","schema"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}