bytedance/deer-flow · warning · HTTPException

{exc}

Error message

{exc}

What it means

Raised as HTTP 422 by POST /api/scheduled-tasks when timezone validation, cron normalization, or compute_next_run_at raises ValueError; the raw exception text becomes the response detail. This is the catch-all for semantically invalid schedule parameters that pass structural checks.

Source

Thrown at backend/app/gateway/routers/scheduled_tasks.py:102

    if body.schedule_type not in {"once", "cron"}:
        raise HTTPException(status_code=422, detail="Unsupported schedule_type")

    schedule_spec = dict(body.schedule_spec)
    try:
        validate_timezone(body.timezone)
        if body.schedule_type == "cron":
            raw_cron = schedule_spec.get("cron")
            if not isinstance(raw_cron, str):
                raise HTTPException(status_code=422, detail="cron schedule requires schedule_spec.cron")
            schedule_spec["cron"] = normalize_cron_expression(raw_cron)
        next_run_at = compute_next_run_at(
            body.schedule_type,
            schedule_spec,
            body.timezone,
            now=datetime.now(UTC),
        )
    except ValueError as exc:
        raise HTTPException(status_code=422, detail=str(exc)) from exc

    if body.schedule_type == "once" and next_run_at is None:
        raise HTTPException(status_code=422, detail="once schedule must be in the future")
    if body.schedule_type == "once" and next_run_at is not None and (next_run_at - datetime.now(UTC)).total_seconds() < config.scheduler.min_once_delay_seconds:
        raise HTTPException(
            status_code=422,
            detail=(f"once schedule must be at least {config.scheduler.min_once_delay_seconds} seconds in the future"),
        )

    return await repo.create(
        task_id=f"task-{uuid.uuid4().hex}",
        user_id=str(user.id),
        thread_id=body.thread_id,
        context_mode=body.context_mode,
        assistant_id="lead_agent",
        title=body.title,
        prompt=body.prompt,
        schedule_type=body.schedule_type,

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Read the detail field — it contains the exact ValueError message naming the bad field.
  2. Use IANA timezone identifiers (e.g. 'Asia/Shanghai', 'America/New_York').
  3. Use a standard 5-field cron expression; validate with a cron library client-side before sending.

Example fix

// before
{ "timezone": "PST", ... }
// after
{ "timezone": "America/Los_Angeles", ... }
Defensive patterns

Strategy: validation

Validate before calling

from zoneinfo import available_timezones
import croniter
assert body["timezone"] in available_timezones(), f"unknown IANA timezone: {body['timezone']}"
croniter.croniter(body["schedule_spec"]["cron"])  # raises on invalid cron before the API call

Type guard

const isValidTimezone = async (tz: string): Promise<boolean> => {
  try { new Intl.DateTimeFormat("en-US", { timeZone: tz }); return true; }
  catch { return false; }
};

Try / catch

resp = requests.post(f"{BASE}/api/scheduled-tasks", json=body, headers=auth)
if resp.status_code == 422:
    show_field_error(resp.json()["detail"])  # detail carries the exact ValueError text
    reopen_schedule_form()

Prevention

When it happens

Trigger: Invalid timezone string (e.g. 'UTC+2' instead of 'Europe/Berlin'), syntactically invalid cron expression that normalization rejects, or a once-schedule run_at that compute_next_run_at cannot parse.

Common situations: Windows-style timezone names; 6-field or 7-field cron expressions when 5 are expected; local time abbreviations like 'PST'.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/754d93a78483d22c. Report an issue: GitHub.