warpdotdev/warp · error · anyhow::Error

Cannot delete schedule with pending changes

Error message

Cannot delete schedule with pending changes

What it means

delete_schedule refuses to enqueue a deletion when the object's metadata reports has_pending_online_only_change() or pending_changes_statuses.pending_delete. This guard prevents issuing a delete that conflicts with unsynced online-only edits or a delete that is already queued for sync.

Source

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

        schedule_id: SyncId,
        ctx: &mut ModelContext<Self>,
    ) -> impl Future<Output = anyhow::Result<()>> + Send + 'static + use<> {
        let id_and_type = CloudObjectTypeAndId::GenericStringObject {
            object_type: GenericStringObjectFormat::Json(JsonObjectType::ScheduledAmbientAgent),
            id: schedule_id,
        };

        let (tx, rx) = oneshot::channel();

        match CloudModel::as_ref(ctx).get_by_uid(&schedule_id.uid()) {
            None => {
                let _ = tx.send(Err(anyhow::anyhow!("Schedule {schedule_id} not found")));
            }
            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))?
        }
    }
}

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Wait for pending changes to flush (poll metadata().pending_changes_statuses until clear) and retry the delete
  2. If a delete is already pending, do not enqueue another - await or surface the existing one's result
  3. Restore connectivity so online-only changes can sync, then retry
  4. If changes stay pending, restart the client to force a cloud reconciliation, then retry

Example fix

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

// after
if let Some(obj) = CloudModel::as_ref(ctx).get_by_uid(&schedule_id.uid()) {
    let m = obj.metadata();
    if m.has_pending_online_only_change() || m.pending_changes_statuses.pending_delete {
        // let sync settle first; surface 'deleting...' state to the user
        return wait_and_retry_delete(schedule_id).await;
    }
}
manager.delete_schedule(schedule_id, ctx).await?;
Defensive patterns

Strategy: validation

Validate before calling

if let Some(obj) = CloudModel::as_ref(ctx).get_by_uid(&schedule_id.uid()) {
    let m = obj.metadata();
    if m.has_pending_online_only_change() || m.pending_changes_statuses.pending_delete {
        // block delete in UI; wait for sync to settle
    }
}

Type guard

fn deletable(obj: &CloudScheduledAmbientAgent) -> bool {
    let m = obj.metadata();
    !m.has_pending_online_only_change() && !m.pending_changes_statuses.pending_delete
}

Try / catch

match manager.delete_schedule(id, ctx).await {
    Err(e) if e.to_string().contains("pending changes") => {
        wait_for_sync(ctx).await; // then retry once
        manager.delete_schedule(id, ctx).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling delete_schedule on a schedule where schedule.metadata().has_pending_online_only_change() is true (an online-only edit not yet acknowledged by the server) or pending_changes_statuses.pending_delete is true (a delete already in flight).

Common situations: User clicks delete twice in quick succession; deleting immediately after editing a schedule while the edit has not synced; an offline period that left pending changes stranded; flaky network that keeps changes pending.

Related errors


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