warpdotdev/warp · error · anyhow::Error

Failed to delete schedule: {}

Error message

Failed to delete schedule: {}

What it means

delete_schedule stores the oneshot sender in self.pending_deletes and the returned future awaits the receiver. If the sender is dropped without ever completing the channel - because the ScheduledAgentManager entity was dropped (app quit) or the sync path that resolves pending_deletes removed the entry without sending - rx.await returns RecvError ('channel closed'), which this message wraps.

Source

Thrown at app/src/ai/ambient_agents/scheduled.rs:387

            Some(schedule) => {
                if schedule.metadata().has_pending_online_only_change()
                    || schedule.metadata().pending_changes_statuses.pending_delete
                {
                    let _ = tx.send(Err(anyhow::anyhow!(
                        "Cannot delete schedule with pending changes"
                    )));
                } else {
                    self.pending_deletes.insert(schedule_id, tx);
                    UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
                        update_manager.delete_object_by_user(id_and_type, ctx);
                    });
                }
            }
        }

        async move {
            rx.await
                .map_err(|e| anyhow::anyhow!("Failed to delete schedule: {}", e))?
        }
    }
}

impl Entity for ScheduledAgentManager {
    type Event = ();
}

impl SingletonEntity for ScheduledAgentManager {}

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Retry delete_schedule after re-checking that the schedule still exists locally
  2. Verify server-side state first: if the object was actually deleted, refresh instead of retrying
  3. Ensure the app is not torn down while pending_deletes is non-empty (drain on shutdown)
  4. Fix or report any sync code path that removes a pending_deletes entry without sending a result

Example fix

// before
manager.delete_schedule(schedule_id, ctx).await?;

// after
match manager.delete_schedule(schedule_id, ctx).await {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().starts_with("Failed to delete schedule") => {
        // channel closed before the ack: verify and retry once
        verify_schedule_gone_server_side(&schedule_id).await?;
        manager.delete_schedule(schedule_id, ctx).await
    }
    Err(e) => Err(e),
}
Defensive patterns

Strategy: retry

Validate before calling

if manager.pending_deletes.contains_key(&schedule_id) {
    // a delete is already awaiting its ack; don't start a second one
}

Try / catch

match manager.delete_schedule(id, ctx).await {
    Err(e) if e.to_string().starts_with("Failed to delete schedule") => {
        verify_server_side_gone(&id).await; // avoid deleting a recreated schedule
        manager.delete_schedule(id, ctx).await
    }
    other => other,
}

Prevention

When it happens

Trigger: The pending_deletes entry keyed by schedule_id is dropped unresolved: app shutdown mid-delete, sync failure path that never sends on the stored tx, or the manager entity being recreated before the cloud delete acknowledgement arrives.

Common situations: Quitting Warp while a schedule deletion is awaiting server confirmation; connectivity loss where the delete ack never arrives and the channel is cleaned up; entity reset during logout/login while deletes are in flight.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/b956d290c1b73f5d. Report an issue: GitHub.