From 8ac52501c38d1a4f8eebbaea35e2287a7748c2a6 Mon Sep 17 00:00:00 2001 From: RKS Date: Sat, 26 Sep 2026 11:40:20 -0400 Subject: [PATCH] fix(storage): preserve running VM delete errors (#1350) * fix(storage): preserve running VM delete errors Do not reinterpret RuntimeError.VMIsRunning as a missing VM when the storage wrapper bridges errors through NSError. Refs #1345 * test(storage): initialize running VM lock file * test(storage): hold VM lock in a child process * fix(storage): narrow file-not-found error matching * test(storage): use Swift error-domain regression coverage --- Sources/tart/VMStorageHelper.swift | 3 ++- Tests/TartTests/CommandBehaviorTests.swift | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Sources/tart/VMStorageHelper.swift b/Sources/tart/VMStorageHelper.swift index 89a47ad..1e523ae 100644 --- a/Sources/tart/VMStorageHelper.swift +++ b/Sources/tart/VMStorageHelper.swift @@ -38,7 +38,8 @@ class VMStorageHelper { extension NSError { func isFileNotFound() -> Bool { - return self.code == NSFileNoSuchFileError || self.code == NSFileReadNoSuchFileError + return self.domain == NSCocoaErrorDomain && + (self.code == NSFileNoSuchFileError || self.code == NSFileReadNoSuchFileError) } } diff --git a/Tests/TartTests/CommandBehaviorTests.swift b/Tests/TartTests/CommandBehaviorTests.swift index c579b0b..b8453c0 100644 --- a/Tests/TartTests/CommandBehaviorTests.swift +++ b/Tests/TartTests/CommandBehaviorTests.swift @@ -116,6 +116,12 @@ final class CommandBehaviorTests: XCTestCase { } } + func testFileNotFoundRequiresCocoaErrorDomain() { + XCTAssertTrue(NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError).isFileNotFound()) + XCTAssertTrue(NSError(domain: NSCocoaErrorDomain, code: NSFileReadNoSuchFileError).isFileNotFound()) + XCTAssertFalse(RuntimeError.VMIsRunning("running").isFileNotFound()) + } + func testSetDiskRejectsStackedVMBeforeSavingConfig() async throws { try await withTemporaryTartHome { let vmDir = try VMStorageLocal().create("stacked")