{"record":{"id":"7313974df827a83c","repo":"langgenius/dify","slug":"the-job-does-not-exist","errorCode":null,"errorMessage":"The job does not exist.","messagePattern":"The job does not exist\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"api/controllers/console/app/annotation.py","lineNumber":272,"sourceCode":"    @console_ns.doc(\"get_annotation_reply_action_status\")\n    @console_ns.doc(description=\"Get status of annotation reply action job\")\n    @console_ns.doc(params={\"app_id\": \"Application ID\", \"job_id\": \"Job ID\", \"action\": \"Action type\"})\n    @console_ns.response(\n        200, \"Job status retrieved successfully\", console_ns.models[AnnotationJobStatusDetailResponse.__name__]\n    )\n    @console_ns.response(403, \"Insufficient permissions\")\n    @setup_required\n    @login_required\n    @account_initialization_required\n    @cloud_edition_billing_resource_check(\"annotation\")\n    @edit_permission_required\n    @rbac_permission_required(RBACResourceScope.APP, RBACPermission.APP_VIEW_LAYOUT)\n    def get(self, app_id: UUID, job_id: UUID, action: str):\n        job_id_str = str(job_id)\n        app_annotation_job_key = f\"{action}_app_annotation_job_{job_id_str}\"\n        cache_result = redis_client.get(app_annotation_job_key)\n        if cache_result is None:\n            raise ValueError(\"The job does not exist.\")\n\n        job_status = cache_result.decode()\n        error_msg = \"\"\n        if job_status == \"error\":\n            app_annotation_error_key = f\"{action}_app_annotation_error_{job_id_str}\"\n            error_msg = redis_client.get(app_annotation_error_key).decode()\n\n        return AnnotationJobStatusDetailResponse(\n            job_id=job_id_str, job_status=job_status, error_msg=error_msg\n        ).model_dump(mode=\"json\"), 200\n\n\n@console_ns.route(\"/apps/<uuid:app_id>/annotations\")\nclass AnnotationApi(Resource):\n    @console_ns.doc(\"list_annotations\")\n    @console_ns.doc(description=\"Get annotations for an app with pagination\")\n    @console_ns.doc(params={\"app_id\": \"Application ID\"})\n    @console_ns.doc(params=query_params_from_model(AnnotationListQuery))","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/annotation.py#L254-L290","documentation":"A ValueError raised in AnnotationReplyActionStatusApi.get: redis_client.get(f'{action}_app_annotation_job_{job_id}') returned None, so the job status is unknown to the API. Annotation reply jobs are tracked as Redis keys (not DB rows), so a missing key means the job never had its status written, already expired, or the action/job_id pair is wrong. It surfaces as a 500 because ValueError is not translated to 404 at this endpoint.","triggerScenarios":"GET /console/apps/<app_id>/annotation-reply/<action>/status/<job_id> where the Redis key for that (action, job_id) does not exist. Reproducible by polling a job_id that was never created, that already completed and its TTL expired, or by passing an action value other than the one used when the job was enqueued.","commonSituations":"Polling a stale job_id after Redis eviction or TTL expiry; wrong action token (e.g. 'import' vs 'export') combined with a real job_id; Redis flushed/restarted between job creation and status poll; job-creation step failed so no key was ever written.","solutions":["Re-trigger the annotation-reply action to produce a fresh job_id, then poll that id with the same action value.","Confirm the action token in the URL matches the action used when the job was created.","Check Redis TTL/eviction policy if keys expire before polling completes; raise maxmemory/retention if needed.","Verify the job-creation call actually succeeded (no exception) so a status key was written before you started polling."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"def job_status_exists(redis_client, action: str, job_id: str) -> bool:\n    return redis_client.get(f'{action}_app_annotation_job_{job_id}') is not None","typeGuard":null,"tryCatchPattern":"try:\n    status = client.get(status_url)\nexcept ValueError as exc:\n    if 'job does not exist' in str(exc).lower():\n        # key missing/expired: re-trigger the action and poll the new job_id\n        new_job = trigger_annotation_action()\n        status = client.get(status_url_for(new_job))\n    raise","preventionTips":["Re-trigger the annotation action to obtain a fresh job_id before polling if the key may have expired.","Keep the action token identical between creation and status polling.","Tune Redis TTL/eviction so status keys survive the expected polling window.","Confirm the job-creation call succeeded before polling its status."],"tags":["annotation","redis","job-status","polling","state"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}