Significant-Gravitas/AutoGPT · error · HTTPException

Schedule #{schedule_id} not found

Error message

Schedule #{schedule_id} not found

What it means

Schedule-deletion endpoint converts a NotFoundError from the scheduler client (`get_scheduler_client().delete_schedule(schedule_id, user_id=user_id)`) into a 404. The call is user-scoped, so the scheduler raises NotFound both when the schedule ID doesn't exist and when it exists but belongs to a different user — identical 404 either way.

Source

Thrown at autogpt_platform/backend/backend/api/features/v1.py:2569

    # the response with a Pydantic validation error.
    return [s for s in schedules if isinstance(s, scheduler.CopilotTurnJobInfo)]


@v1_router.delete(
    path="/schedules/{schedule_id}",
    summary="Delete execution schedule",
    tags=["schedules"],
    dependencies=[Security(requires_user)],
)
async def delete_graph_execution_schedule(
    user_id: Annotated[str, Security(get_user_id)],
    ctx: Annotated[RequestContext, Security(get_request_context)],
    schedule_id: str = Path(..., description="ID of the schedule to delete"),
) -> dict[str, Any]:
    try:
        await get_scheduler_client().delete_schedule(schedule_id, user_id=user_id)
    except NotFoundError:
        raise HTTPException(
            status_code=HTTP_404_NOT_FOUND,
            detail=f"Schedule #{schedule_id} not found",
        )
    return {"id": schedule_id}


########################################################
##################### COPILOT SKILLS #####################
########################################################


class CopilotSkillInfo(BaseModel):
    """User-distilled copilot skill metadata for the library UI.

    Defaults (built-in agent-building / MCP-tool guides) are intentionally
    excluded — they cannot be edited or deleted, so surfacing them in the
    user-facing list would add noise without affordances.
    """

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Refresh the schedules list and reconcile client state — a 404 on delete usually means already gone, which is safe to treat as success in the UI.
  2. Confirm the schedule_id comes from the authenticated user's own list.
  3. If the scheduler was wiped but the UI still lists schedules, re-sync by re-fetching from the scheduler-backed list endpoint.

Example fix

// before
await api.deleteSchedule(id);
// after — treat 404 as idempotent success
const res = await api.deleteSchedule(id);
if (res.status === 404) { /* already deleted */ }
Defensive patterns

Strategy: fallback

Validate before calling

const schedules = await api.listSchedules();
const exists = schedules.some(s => s.id === scheduleId);
if (!exists) { removeScheduleFromUi(scheduleId); return; }

Try / catch

try {
  await api.deleteSchedule(scheduleId);
} catch (e) {
  if (e.status === 404) { removeScheduleFromUi(scheduleId); return; } // idempotent
  throw e;
}

Prevention

When it happens

Trigger: DELETE /v1/schedules/{schedule_id} where the ID is wrong, the schedule was already deleted (double-delete), or it belongs to another user.

Common situations: Two clicks on a delete button with the second racing the first; UI list out of sync with the scheduler; environments where the scheduler service was reset (redis-backed scheduler lost its jobs) while the DB list still shows them.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/c4f0cc5e442791b4. Report an issue: GitHub.