HKUDS/DeepTutor · error · ValueError

message is required

Error message

message is required

What it means

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).

Source

Thrown at deeptutor/services/cron/service.py:239

        tmp = self.store_path.with_suffix(".tmp")
        tmp.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
        tmp.replace(self.store_path)

    # ── job management ────────────────────────────────────────────

    def add_job(
        self,
        *,
        name: str,
        message: str,
        schedule: CronSchedule,
        owner: CronOwner,
        delete_after_run: bool | None = None,
    ) -> CronJob:
        self._load()
        validate_schedule(schedule)
        if not message.strip():
            raise ValueError("message is required")
        job = CronJob(
            id=uuid.uuid4().hex[:10],
            name=name.strip() or message.strip()[:48],
            message=message.strip(),
            schedule=schedule,
            owner=owner,
            # One-shot jobs clean up after themselves unless told otherwise.
            delete_after_run=(
                delete_after_run if delete_after_run is not None else schedule.kind == "at"
            ),
            created_at_ms=_now_ms(),
        )
        job.state.next_run_at_ms = compute_next_run(schedule, _now_ms())
        self._jobs[job.id] = job
        self._save()
        self._wake.set()
        return job

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Require a non-empty message in the UI/API before calling add_job
  2. Strip and check client-side: if not message.strip(): return an error
  3. Always pass a meaningful prompt string when creating jobs programmatically

Example fix

# before
svc.add_job(name="reminder", message="   ", schedule=sched, owner=owner)
# after
msg = (user_input or "").strip()
if not msg:
    raise HTTPException(400, "message is required")
svc.add_job(name="reminder", message=msg, schedule=sched, owner=owner)
Defensive patterns

Strategy: validation

Validate before calling

message = (message or "").strip()
if not message:
    raise ValueError("message is required")
svc.add_job(message=message, ...)

Try / catch

try:
    svc.add_job(message=raw, ...)
except ValueError as e:
    if "message is required" in str(e):
        return bad_request("cron message cannot be empty")
    raise

Prevention

When it happens

Trigger: svc.add_job(message=" ", schedule=..., owner=...) or message="" — typically from a form/API where the field was optional and left blank.

Common situations: 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 ''.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/6aa35c9b8d5977e4. Report an issue: GitHub.