{"record":{"id":"c5c6e0970abd34d9","repo":"PaddlePaddle/PaddleOCR","slug":"job-task-mismatch-expected-task-got-job-task","errorCode":null,"errorMessage":"Job task mismatch: expected {task}, got {job.task}.","messagePattern":"Job task mismatch: expected (.+?), got (.+?)\\.","errorType":"validation","errorClass":"InvalidRequestError","httpStatus":null,"severity":"error","filePath":"paddleocr/_api_client/_core.py","lineNumber":94,"sourceCode":") -> DocParsingOptions:\n    if options is not None:\n        if model == Model.PP_STRUCTURE_V3 and not isinstance(\n            options, PPStructureV3Options\n        ):\n            raise InvalidRequestError(\"PP-StructureV3 requires PPStructureV3Options.\")\n        if is_vl_model(model) and not isinstance(options, PaddleOCRVLOptions):\n            raise InvalidRequestError(\"PaddleOCR-VL models require PaddleOCRVLOptions.\")\n        return options\n    if model == Model.PP_STRUCTURE_V3:\n        return PPStructureV3Options()\n    return PaddleOCRVLOptions()\n\n\ndef job_id_for_task(job: Union[Job, str], task: str) -> str:\n    if isinstance(job, str):\n        return job\n    if job.task != task:\n        raise InvalidRequestError(\n            f\"Job task mismatch: expected {task}, got {job.task}.\"\n        )\n    if task == \"ocr\" and not is_ocr_model(job.model):\n        raise InvalidRequestError(f\"Job model is not an OCR model: {job.model}.\")\n    if task == \"document_parsing\" and not is_document_parsing_model(job.model):\n        raise InvalidRequestError(\n            f\"Job model is not a document parsing model: {job.model}.\"\n        )\n    return job.job_id\n\n\ndef extract_api_message_from_payload(payload: dict) -> Optional[str]:\n    for key in (\"msg\", \"errorMsg\", \"message\"):\n        value = payload.get(key)\n        if value:\n            return str(value)\n    data = payload.get(\"data\")\n    if isinstance(data, dict):","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_core.py#L76-L112","documentation":"Raised as InvalidRequestError by job_id_for_task() when a Job object is passed to a task-scoped method (e.g. result fetching for 'ocr') but the job's task attribute differs. This prevents, for example, feeding a document-parsing job into an OCR result endpoint.","triggerScenarios":"Passing a Job returned from a document-parsing create call to an OCR-specific method (or vice versa); the job.task string does not equal the method's expected task name.","commonSituations":"Mixed pipelines handling both OCR and document parsing that share one variable for 'current job', or copy-pasted follow-up calls after switching endpoint.","solutions":["Route each Job to the follow-up method matching its task.","Check job.task before dispatching, or just pass the job_id string if you know the endpoint.","Keep OCR and document-parsing jobs in separate variables/queues."],"exampleFix":"# before\nocr_result = await client.get_ocr_result(doc_job)  # doc_job.task == 'document_parsing'\n\n# after\nif doc_job.task == \"document_parsing\":\n    result = await client.get_document_parsing_result(doc_job)","handlingStrategy":"type-guard","validationCode":"def route_job(job, ocr_fn, doc_fn):\n    return ocr_fn(job) if job.task == \"ocr\" else doc_fn(job)","typeGuard":"def is_task(job, task: str) -> bool:\n    return job.task == task","tryCatchPattern":null,"preventionTips":["Store the task name with the job id when persisting.","Never share one 'current job' variable between OCR and document-parsing flows."],"tags":["validation","job","task","client-side"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}