datawhalechina/hello-agents · warning · HTTPException

任务不存在

Error message

任务不存在

What it means

HTTPException 404 '任务不存在' raised at api/routes/tasks.py:111 when agent_controller.get_task_status returns a falsy value for the requested task_id. It means the controller has no record of the task — the task was never submitted, was cleaned up, or lived only in memory lost on restart.

Source

Thrown at Co-creation-projects/Apricity-InnocoreAI/api/routes/tasks.py:111

        result = await agent_controller.execute_task(task_id)
        
        return {
            "success": True,
            "task_id": task_id,
            "result": result
        }
        
    except Exception as e:
        logger.error(f"执行任务失败: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@router.get("/{task_id}/status", response_model=TaskResponse)
async def get_task_status(task_id: str):
    """获取任务状态"""
    try:
        status = await agent_controller.get_task_status(task_id)
        if not status:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        return TaskResponse(**status)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取任务状态失败: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@router.delete("/{task_id}", response_model=Dict[str, Any])
async def cancel_task(task_id: str):
    """取消任务"""
    try:
        success = await agent_controller.cancel_task(task_id)
        
        if success:
            return {"success": True, "message": "任务已取消"}
        else:

View on GitHub (pinned to 606a07d341)

Solutions

  1. Confirm the task_id by listing tasks via GET /tasks/ and matching ids.
  2. If the server restarted, re-submit the task — in-memory registries do not survive restarts.
  3. Persist task records (the history store) if ids must survive restarts.
  4. On the client, treat 404 on status polls as terminal and stop polling.

Example fix

// before
resp = await client.get(f"/tasks/{task_id}/status")
resp.raise_for_status()
// after
resp = await client.get(f"/tasks/{task_id}/status")
if resp.status_code == 404:
    # task unknown/evicted: stop polling, optionally resubmit
    return None
resp.raise_for_status()
Defensive patterns

Strategy: try-catch

Validate before calling

resp = await client.get(f"/tasks/{task_id}/status")
if resp.status_code == 404:
    stop_polling()  # task unknown or evicted

Type guard

def task_exists(resp) -> bool:
    return resp.status_code != 404

Try / catch

try:
    status = get_task_status(task_id)
except HTTPException as e:
    if e.status_code == 404:
        return None  # terminal; stop polling
    raise

Prevention

When it happens

Trigger: GET /tasks/{task_id}/status with a typo'd or stale task_id; task finished and evicted from the history list; server restarted so in-memory task registry was wiped; task cancelled and removed.

Common situations: Client holds a task_id from a previous deployment/session; in-memory task storage without persistence; polling after the retention window expired.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/229a598a250b743a. Report an issue: GitHub.