warpdotdev/warp · error · anyhow::Error
Schedule not found
Error message
Schedule not found
What it means
Thrown by ScheduledAgentManager::modify_schedule when CloudScheduledAmbientAgent::get_by_id(&schedule_id, ctx) returns None. pause_schedule and update_schedule both funnel through this helper, so any modify operation on a schedule that is not present in the local cloud-object snapshot fails immediately with this message before UpdateManager is ever involved.
Source
Thrown at app/src/ai/ambient_agents/scheduled.rs:247
let update_future =
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.update_scheduled_ambient_agent_online(
updated_config,
schedule_id,
revision,
ctx,
)
});
async move {
update_future
.await
.map_err(|e| anyhow::anyhow!("{}: {}", error_message, e))
}
.boxed()
}
None => async move { Err(anyhow::anyhow!("Schedule not found")) }.boxed(),
}
}
/// Pause a scheduled ambient agent.
pub fn pause_schedule(
&mut self,
schedule_id: SyncId,
ctx: &mut ModelContext<Self>,
) -> impl Future<Output = anyhow::Result<()>> + Send + 'static + use<> {
self.modify_schedule(
schedule_id,
"Failed to pause schedule",
|config| config.enabled = false,
ctx,
)
}
/// Unpause a scheduled ambient agent.View on GitHub (pinned to e72fd7aacb)
Solutions
- Refresh scheduled agents from the cloud and re-render the list, then retry with the current id
- Guard the call: check CloudScheduledAmbientAgent::get_by_id(&schedule_id, ctx).is_some() before invoking pause/update
- If the UI row is already gone, treat 'Schedule not found' as a benign no-op success
- Check pending_deletes / pending_changes state to detect a concurrent delete before acting
Example fix
// before
manager.pause_schedule(schedule_id, ctx).await?;
// after
if CloudScheduledAmbientAgent::get_by_id(&schedule_id, ctx).is_some() {
manager.pause_schedule(schedule_id, ctx).await?;
} else {
// schedule vanished locally: refresh from cloud instead of failing
refresh_schedules(ctx).await?;
} Defensive patterns
Strategy: validation
Validate before calling
let exists = CloudScheduledAmbientAgent::get_by_id(&schedule_id, ctx).is_some();
if !exists {
// stale id: refresh schedules from cloud / drop the UI row instead of calling modify
} Type guard
fn schedule_exists(id: &SyncId, ctx: &AppContext) -> bool {
CloudScheduledAmbientAgent::get_by_id(id, ctx).is_some()
} Try / catch
match manager.pause_schedule(id, ctx).await {
Ok(()) => {}
Err(e) if e.to_string() == "Schedule not found" => { /* benign: refresh list */ }
Err(e) => return Err(e),
} Prevention
- Always resolve schedule ids from the freshly rendered list, never from persisted stale state
- Drop or refresh UI rows as soon as deletion is confirmed so modify actions cannot target them
- Treat 'Schedule not found' as idempotent success when the user's intent is already satisfied
When it happens
Trigger: Calling pause_schedule(schedule_id, ctx), update_schedule(...), or any other modify_schedule wrapper with a SyncId whose CloudScheduledAmbientAgent object no longer exists locally (get_by_id -> None at scheduled.rs:221).
Common situations: Stale schedule list in the UI after the schedule was deleted from another device or by an already-synced pending delete; a race between a delete confirmation and a pause/resume click; a schedule id persisted from a previous app session that was since removed server-side.
Related errors
- Schedule {schedule_id} not found
- Cannot delete schedule with pending changes
- Failed to delete schedule: {}
- invalid value 'schedule'
- Cloud follow-up did not start in time
AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16).
Data as JSON: /api/errors/b972c58ca842b9c2.
Report an issue: GitHub.