HKUDS/DeepTutor · error · ValueError
unknown schedule kind {schedule.kind!r}
Error message
unknown schedule kind {schedule.kind!r} What it means
validate_schedule ends with a fallthrough raise for any schedule kind other than 'at', 'every', and 'cron'. kind is an open string, so a typo, legacy, or future kind is rejected with the offending value in the message.
Source
Thrown at deeptutor/services/cron/service.py:175
raise ValueError("'at' time is in the past")
return
if schedule.kind == "every":
if not schedule.every_seconds or schedule.every_seconds < 30:
raise ValueError("'every' interval must be at least 30 seconds")
return
if schedule.kind == "cron":
if schedule.tz:
try:
from zoneinfo import ZoneInfo
ZoneInfo(schedule.tz)
except Exception:
raise ValueError(f"unknown timezone {schedule.tz!r}") from None
# Raises ValueError on bad/unsupported expressions.
if compute_next_run(schedule, _now_ms()) is None:
raise ValueError(f"cron expression {schedule.expr!r} never fires")
return
raise ValueError(f"unknown schedule kind {schedule.kind!r}")
class CronService:
"""Single-process job store + scheduler."""
def __init__(
self,
store_path: Path,
on_job: Callable[[CronJob], Awaitable[tuple[str, str | None]]] | None = None,
) -> None:
"""``on_job`` returns ``(status, error)`` with status ok/error/skipped."""
self.store_path = store_path
self.on_job = on_job
self._jobs: dict[str, CronJob] = {}
self._loaded = False
self._timer_task: asyncio.Task | None = None
self._wake = asyncio.Event()
self._running = FalseView on GitHub (pinned to 3e82f13042)
Solutions
- Use one of the exact kinds: 'at', 'every', or 'cron'
- Map legacy kind names to the current three during migration before calling add_job
- Validate kind at the API boundary and return 400 with the allowed values
Example fix
# before
sched = CronSchedule(kind="daily", every_seconds=86400) # ValueError
# after
sched = CronSchedule(kind="every", every_seconds=86400)
# migration:
LEGACY = {"daily": "every", "once": "at", "recurring": "every"}
kind = LEGACY.get(raw_kind, raw_kind) Defensive patterns
Strategy: type-guard
Validate before calling
ALLOWED_KINDS = {"at", "every", "cron"}
assert schedule.kind in ALLOWED_KINDS, f"kind must be one of {ALLOWED_KINDS}" Type guard
def is_known_schedule_kind(s: CronSchedule) -> bool:
return s.kind in {"at", "every", "cron"} Try / catch
try:
svc.add_job(schedule, ...)
except ValueError as e:
if "unknown schedule kind" in str(e):
return bad_request(f"kind must be at/every/cron, got {schedule.kind!r}")
raise Prevention
- Validate kind with a Literal/enum at your API schema
- Map legacy kind names during migrations
When it happens
Trigger: CronSchedule(kind="daily"), kind="Once", or a deserialized record with an empty/renamed kind passed to add_job.
Common situations: Schema evolution renaming kinds; typos from config files or user input; old persisted jobs replayed against a newer service that dropped a kind.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- invalid cron expression {schedule.expr!r}: {exc}
- 'at' schedules need a time
- 'at' time is in the past
- 'every' interval must be at least 30 seconds
- unknown timezone {schedule.tz!r}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/78db4a5c4a9fd15e.
Report an issue: GitHub.