@@ -246,24 +246,30 @@ export class ArchiveService {
246246 archivedTask . branchName = actualBranch ;
247247 }
248248
249- await step (
250- async ( ) => {
251- if ( ! archivedTask . checkpointId ) {
252- throw new Error ( "checkpointId must be set for worktree mode" ) ;
253- }
254- await this . captureWorktreeCheckpoint (
255- folderPath ,
256- worktreePath ,
257- archivedTask . checkpointId ,
258- ) ;
259- } ,
260- async ( ) => {
261- if ( archivedTask . checkpointId ) {
249+ const checkpointId = archivedTask . checkpointId ;
250+ try {
251+ if ( ! checkpointId ) {
252+ throw new Error ( "checkpointId must be set for worktree mode" ) ;
253+ }
254+ await step (
255+ ( ) =>
256+ this . captureWorktreeCheckpoint (
257+ folderPath ,
258+ worktreePath ,
259+ checkpointId ,
260+ ) ,
261+ async ( ) => {
262262 const git = createGitClient ( folderPath ) ;
263- await deleteCheckpoint ( git , archivedTask . checkpointId ) ;
264- }
265- } ,
266- ) ;
263+ await deleteCheckpoint ( git , checkpointId ) ;
264+ } ,
265+ ) ;
266+ } catch ( error ) {
267+ this . log . warn (
268+ `Failed to capture checkpoint for ${ worktreePath } ; archiving without a restore point` ,
269+ { error } ,
270+ ) ;
271+ archivedTask . checkpointId = null ;
272+ }
267273 }
268274
269275 await step (
@@ -277,13 +283,39 @@ export class ArchiveService {
277283
278284 await step (
279285 async ( ) => {
280- const manager = new WorktreeManager ( {
281- mainRepoPath : folderPath ,
282- worktreeBasePath : this . workspaceSettings . getWorktreeLocation ( ) ,
283- } ) ;
284- await manager . deleteWorktree ( worktreePath ) ;
285- const parentDir = path . dirname ( worktreePath ) ;
286- await forceRemove ( parentDir ) ;
286+ try {
287+ const manager = new WorktreeManager ( {
288+ mainRepoPath : folderPath ,
289+ worktreeBasePath : this . workspaceSettings . getWorktreeLocation ( ) ,
290+ } ) ;
291+ await manager . deleteWorktree ( worktreePath ) ;
292+ const parentDir = path . dirname ( worktreePath ) ;
293+ await forceRemove ( parentDir ) ;
294+ } catch ( error ) {
295+ this . log . warn (
296+ `Failed to remove worktree at ${ worktreePath } ; archiving anyway (on-disk worktree may need manual cleanup)` ,
297+ { error } ,
298+ ) ;
299+ // The worktree is still registered under its original name, so a
300+ // later unarchive can't re-add it from the checkpoint (git rejects
301+ // the duplicate name/path), leaving the task un-restorable. Drop
302+ // the restore point — and its now-orphaned checkpoint ref — so the
303+ // archive record stays internally consistent, matching how a
304+ // failed capture above already sets checkpointId to null.
305+ const orphanedCheckpointId = archivedTask . checkpointId ;
306+ if ( orphanedCheckpointId ) {
307+ archivedTask . checkpointId = null ;
308+ try {
309+ const git = createGitClient ( folderPath ) ;
310+ await deleteCheckpoint ( git , orphanedCheckpointId ) ;
311+ } catch ( cleanupError ) {
312+ this . log . warn (
313+ `Failed to delete orphaned checkpoint ${ orphanedCheckpointId } ` ,
314+ { error : cleanupError } ,
315+ ) ;
316+ }
317+ }
318+ }
287319 } ,
288320 async ( ) => { } ,
289321 ) ;
0 commit comments