{"record":{"id":"754d93a78483d22c","repo":"bytedance/deer-flow","slug":"exc","errorCode":null,"errorMessage":"{exc}","messagePattern":"\\{exc\\}","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"warning","filePath":"backend/app/gateway/routers/scheduled_tasks.py","lineNumber":102,"sourceCode":"    if body.schedule_type not in {\"once\", \"cron\"}:\n        raise HTTPException(status_code=422, detail=\"Unsupported schedule_type\")\n\n    schedule_spec = dict(body.schedule_spec)\n    try:\n        validate_timezone(body.timezone)\n        if body.schedule_type == \"cron\":\n            raw_cron = schedule_spec.get(\"cron\")\n            if not isinstance(raw_cron, str):\n                raise HTTPException(status_code=422, detail=\"cron schedule requires schedule_spec.cron\")\n            schedule_spec[\"cron\"] = normalize_cron_expression(raw_cron)\n        next_run_at = compute_next_run_at(\n            body.schedule_type,\n            schedule_spec,\n            body.timezone,\n            now=datetime.now(UTC),\n        )\n    except ValueError as exc:\n        raise HTTPException(status_code=422, detail=str(exc)) from exc\n\n    if body.schedule_type == \"once\" and next_run_at is None:\n        raise HTTPException(status_code=422, detail=\"once schedule must be in the future\")\n    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:\n        raise HTTPException(\n            status_code=422,\n            detail=(f\"once schedule must be at least {config.scheduler.min_once_delay_seconds} seconds in the future\"),\n        )\n\n    return await repo.create(\n        task_id=f\"task-{uuid.uuid4().hex}\",\n        user_id=str(user.id),\n        thread_id=body.thread_id,\n        context_mode=body.context_mode,\n        assistant_id=\"lead_agent\",\n        title=body.title,\n        prompt=body.prompt,\n        schedule_type=body.schedule_type,","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/scheduled_tasks.py#L84-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"Windows-style timezone names; 6-field or 7-field cron expressions when 5 are expected; local time abbreviations like 'PST'.","solutions":["Read the detail field — it contains the exact ValueError message naming the bad field.","Use IANA timezone identifiers (e.g. 'Asia/Shanghai', 'America/New_York').","Use a standard 5-field cron expression; validate with a cron library client-side before sending."],"exampleFix":"// before\n{ \"timezone\": \"PST\", ... }\n// after\n{ \"timezone\": \"America/Los_Angeles\", ... }","handlingStrategy":"validation","validationCode":"from zoneinfo import available_timezones\nimport croniter\nassert body[\"timezone\"] in available_timezones(), f\"unknown IANA timezone: {body['timezone']}\"\ncroniter.croniter(body[\"schedule_spec\"][\"cron\"])  # raises on invalid cron before the API call","typeGuard":"const isValidTimezone = async (tz: string): Promise<boolean> => {\n  try { new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }); return true; }\n  catch { return false; }\n};","tryCatchPattern":"resp = requests.post(f\"{BASE}/api/scheduled-tasks\", json=body, headers=auth)\nif resp.status_code == 422:\n    show_field_error(resp.json()[\"detail\"])  # detail carries the exact ValueError text\n    reopen_schedule_form()","preventionTips":["Always use IANA timezone names; never offsets or abbreviations.","Pre-validate cron with the same library semantics (5-field) the backend uses.","Surface the 422 detail verbatim in the form — it names the offending field."],"tags":["scheduled-tasks","cron","timezone","validation","http-422"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}