bytedance/deer-flow · info · HTTPException

Scheduled task not found

Error message

Scheduled task not found

What it means

Raised as HTTP 404 by GET /api/scheduled-tasks/{task_id} when repo.get(task_id, user_id=...) returns None — the task id does not exist or belongs to a different user. The repository query is scoped to the requesting user, so foreign tasks are reported as not found.

Source

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

        title=body.title,
        prompt=body.prompt,
        schedule_type=body.schedule_type,
        schedule_spec=schedule_spec,
        timezone=body.timezone,
        next_run_at=next_run_at,
    )


@router.get("/scheduled-tasks/{task_id}")
@require_permission("threads", "read")
async def get_scheduled_task(task_id: str, request: Request):
    repo = get_scheduled_task_repo(request)
    user = await get_optional_user_from_request(request)
    if user is None:
        raise HTTPException(status_code=401, detail="Authentication required")
    task = await repo.get(task_id, user_id=str(user.id))
    if task is None:
        raise HTTPException(status_code=404, detail="Scheduled task not found")
    return task


@router.patch("/scheduled-tasks/{task_id}")
@require_permission("threads", "write")
async def update_scheduled_task(task_id: str, request: Request, body: ScheduledTaskUpdateRequest):
    config = get_config()
    repo = get_scheduled_task_repo(request)
    user = await get_optional_user_from_request(request)
    if user is None:
        raise HTTPException(status_code=401, detail="Authentication required")
    existing = await repo.get(task_id, user_id=str(user.id))
    if existing is None:
        raise HTTPException(status_code=404, detail="Scheduled task not found")
    _ensure_task_mutable(existing)

    updates = body.model_dump(exclude_none=True)
    if "context_mode" in updates:

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. List your tasks via GET /api/scheduled-tasks and use a current task id.
  2. Treat 404 as terminal in polling loops — stop refreshing that task.
  3. Confirm you are authenticated as the user who created the task.

Example fix

// before
const task = await api.getTask(id); // throws on 404
// after
const res = await api.getTaskRaw(id);
if (res.status === 404) { removeTaskFromUi(id); return null; }
return res.data;
Defensive patterns

Strategy: try-catch

Validate before calling

tasks = requests.get(f"{BASE}/api/scheduled-tasks", headers=auth).json()
owned_ids = {t["id"] for t in tasks}
if task_id not in owned_ids:
    remove_task_from_ui(task_id)  # gone or not owned — terminal

Type guard

def is_owned_task(tid: str, listed: list[dict]) -> bool:
    return any(t.get("id") == tid for t in listed)

Try / catch

resp = requests.get(f"{BASE}/api/scheduled-tasks/{task_id}", headers=auth)
if resp.status_code == 404:
    remove_task_from_ui(task_id)  # do not retry; do not leak existence assumptions
else:
    resp.raise_for_status()

Prevention

When it happens

Trigger: Fetching a deleted task, a typo'd task id, or a task created by another account; also after the scheduler's retention removes old tasks.

Common situations: Stale task id in the UI after deletion; sharing task links between users; polling a completed-and-pruned task.

Related errors


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