{"record":{"id":"6aa35c9b8d5977e4","repo":"HKUDS/DeepTutor","slug":"message-is-required","errorCode":null,"errorMessage":"message is required","messagePattern":"message is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/cron/service.py","lineNumber":239,"sourceCode":"        tmp = self.store_path.with_suffix(\".tmp\")\n        tmp.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding=\"utf-8\")\n        tmp.replace(self.store_path)\n\n    # ── job management ────────────────────────────────────────────\n\n    def add_job(\n        self,\n        *,\n        name: str,\n        message: str,\n        schedule: CronSchedule,\n        owner: CronOwner,\n        delete_after_run: bool | None = None,\n    ) -> CronJob:\n        self._load()\n        validate_schedule(schedule)\n        if not message.strip():\n            raise ValueError(\"message is required\")\n        job = CronJob(\n            id=uuid.uuid4().hex[:10],\n            name=name.strip() or message.strip()[:48],\n            message=message.strip(),\n            schedule=schedule,\n            owner=owner,\n            # One-shot jobs clean up after themselves unless told otherwise.\n            delete_after_run=(\n                delete_after_run if delete_after_run is not None else schedule.kind == \"at\"\n            ),\n            created_at_ms=_now_ms(),\n        )\n        job.state.next_run_at_ms = compute_next_run(schedule, _now_ms())\n        self._jobs[job.id] = job\n        self._save()\n        self._wake.set()\n        return job\n","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/cron/service.py#L221-L257","documentation":"CronService.add_job validates the schedule, then rejects a message that is empty or whitespace-only, because every cron job must carry the message to deliver when it fires. The message also drives the default job name (first 48 chars).","triggerScenarios":"svc.add_job(message=\"   \", schedule=..., owner=...) or message=\"\" — typically from a form/API where the field was optional and left blank.","commonSituations":"UI submitting before the user typed the prompt; input trimmed to empty before being passed through; integration payloads where the message key is absent and defaults to ''.","solutions":["Require a non-empty message in the UI/API before calling add_job","Strip and check client-side: if not message.strip(): return an error","Always pass a meaningful prompt string when creating jobs programmatically"],"exampleFix":"# before\nsvc.add_job(name=\"reminder\", message=\"   \", schedule=sched, owner=owner)\n# after\nmsg = (user_input or \"\").strip()\nif not msg:\n    raise HTTPException(400, \"message is required\")\nsvc.add_job(name=\"reminder\", message=msg, schedule=sched, owner=owner)","handlingStrategy":"validation","validationCode":"message = (message or \"\").strip()\nif not message:\n    raise ValueError(\"message is required\")\nsvc.add_job(message=message, ...)","typeGuard":null,"tryCatchPattern":"try:\n    svc.add_job(message=raw, ...)\nexcept ValueError as e:\n    if \"message is required\" in str(e):\n        return bad_request(\"cron message cannot be empty\")\n    raise","preventionTips":["Strip and require non-empty message in forms","Make message a required field in API schemas"],"tags":["cron","validation","required-field"],"backgroundTag":"required-field-missing","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}