From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 3C8431FF13B for ; Wed, 11 Feb 2026 16:24:56 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6C87731C09; Wed, 11 Feb 2026 16:25:41 +0100 (CET) From: Christian Ebner To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup] fix #7305: client: restore: filter out last snapshot if not finished Date: Wed, 11 Feb 2026 16:24:52 +0100 Message-ID: <20260211152452.894157-1-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1770823422469 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.048 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 5BAEWN7ESBBPWLC5NHYSFIHTUSWXMSNL X-Message-ID-Hash: 5BAEWN7ESBBPWLC5NHYSFIHTUSWXMSNL X-MailFrom: c.ebner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: When invoking the client CLI for restore via: ``` proxmox-backup-client restore ``` the provide a backup group only, in which case the client falls back to restore the last snapshot of that group as convenience. The snapshot listing used to identify the last snapshot returns however all snapshots, including unfinished ones, a restore on an unfinished one will therefore fail. Fix this by filtering out snapshots which do not contain a manifest file yet, and therefore are not considered as finished. Also adapt the helper function name to reflect this change. Ideally this would happen on the server side, guarded by some flag, but that will not work with older server versions. Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=7305 Signed-off-by: Christian Ebner --- Note: The behaviour can be easily tested by simply temporarily renaming the index.json.blob in the last snapshot of a backup group to simulate an ongoing backup for that snapshot. proxmox-backup-client/src/main.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs index 999e50205..7e20b9cc8 100644 --- a/proxmox-backup-client/src/main.rs +++ b/proxmox-backup-client/src/main.rs @@ -160,7 +160,7 @@ async fn api_datastore_list_snapshots( Ok(result["data"].take()) } -pub async fn api_datastore_latest_snapshot( +pub async fn api_datastore_latest_finished_snapshot( client: &HttpClient, store: &str, ns: &BackupNamespace, @@ -175,6 +175,21 @@ pub async fn api_datastore_latest_snapshot( list.sort_unstable_by(|a, b| b.backup.time.cmp(&a.backup.time)); + // only once a snapshots contains the manifest it is considered finished + let last_is_finished = list[0] + .files + .iter() + .any(|content| content.filename == MANIFEST_BLOB_NAME.as_ref()); + + if !last_is_finished { + if list.len() > 1 { + log::info!("last snapshot of group {group} not finished, use previous instead"); + return Ok((group, list[1].backup.time).into()); + } else { + bail!("backup group {group} does not contain finished snapshots."); + } + } + Ok((group, list[0].backup.time).into()) } @@ -187,7 +202,7 @@ pub async fn dir_or_last_from_group( match path.parse::()? { BackupPart::Dir(dir) => Ok(dir), BackupPart::Group(group) => { - api_datastore_latest_snapshot(client, repo.store(), ns, group).await + api_datastore_latest_finished_snapshot(client, repo.store(), ns, group).await } } } -- 2.47.3