{"record":{"id":"905976b9ec2edd28","repo":"HKUDS/Vibe-Trading","slug":"job-id-is-required-for-propose-cancel","errorCode":null,"errorMessage":"job_id is required for propose_cancel","messagePattern":"job_id is required for propose_cancel","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/scheduled_research_tool.py","lineNumber":123,"sourceCode":"                ]\n            }\n        elif action == \"get_job\":\n            job_id = str(kwargs.get(\"job_id\") or \"\").strip()\n            job = default_store().get(job_id)\n            if job is None:\n                raise ValueError(f\"scheduled research job {job_id!r} was not found\")\n            payload = public_job(job)\n        elif action == \"list_playbooks\":\n            payload = {\"playbooks\": [item.to_dict() for item in list_playbooks()]}\n        elif action == \"propose_create\":\n            draft = kwargs.get(\"draft\")\n            if not isinstance(draft, dict):\n                raise ValueError(\"draft is required for propose_create\")\n            payload = propose_create(draft, session_id=session_id)\n        elif action == \"propose_cancel\":\n            job_id = str(kwargs.get(\"job_id\") or \"\").strip()\n            if not job_id:\n                raise ValueError(\"job_id is required for propose_cancel\")\n            payload = propose_cancel(job_id, session_id=session_id)\n        else:\n            raise ValueError(f\"unsupported scheduled_research action {action!r}\")\n        return json.dumps(payload, ensure_ascii=False)\n","sourceCodeStart":105,"sourceCodeEnd":128,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/scheduled_research_tool.py#L105-L128","documentation":"The scheduled_research tool was invoked with action='propose_cancel' but no usable job_id kwarg. The tool strips whitespace and treats empty/missing values as absent, then raises ValueError before calling propose_cancel. It is a usage error from the tool's public execute method.","triggerScenarios":"Calling the scheduled_research tool with {\"action\": \"propose_cancel\"} without job_id, or with job_id set to \"\" / None / a whitespace-only string (str(kwargs.get(\"job_id\") or \"\").strip() is empty).","commonSituations":"An LLM agent or script composes the tool call and omits job_id because it doesn't know the previously created job's ID, or passes job_id=0/empty string assuming it defaults.","solutions":["Pass a non-empty job_id kwarg, e.g. {\"action\": \"propose_cancel\", \"job_id\": \"<id from propose_create response>\"}","If you don't know the job_id, first list/lookup scheduled jobs (e.g. via the propose_create response payload or the scheduling API) to obtain it","Ensure upstream code forwards the job_id returned when the job was proposed instead of dropping the field"],"exampleFix":"# before\nresult = tool.execute(action=\"propose_cancel\")\n# after\nresult = tool.execute(action=\"propose_cancel\", job_id=\"job-2024-001\")","handlingStrategy":"validation","validationCode":"job_id = (kwargs.get(\"job_id\") or \"\").strip()\nif not job_id:\n    raise RuntimeError(\"need job_id from the propose_create response before cancelling\")\nresult = tool.execute(action=\"propose_cancel\", job_id=job_id)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Persist the job_id returned by propose_create and reuse it for propose_cancel","Validate non-empty job_id in the caller before invoking the tool"],"tags":["scheduled-research","tool-args","missing-parameter","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}