After upgrading to Xcode 26.4, a unit test without a host application may fail to load a project-root .env file, JSON fixture, or other file referenced by a relative path. The log can report No such file or directory and show that the path was resolved under /tmp. Xcode 26.4 made /tmp the consistent default working directory for this kind of test runner in both Xcode and xcodebuild. This guide explains how to identify the problem and remove the fragile working-directory dependency.
Representative error
Error Domain=NSCocoaErrorDomain Code=260
"The file “.env” couldn’t be opened because there is no such file."
Underlying error: No such file or directory
Path: /tmp/.env
Depending on the loader, the same failure may appear as POSIXErrorCode.ENOENT, No such file or directory (2), or Failed to load .env. The diagnostic clue is that the resolved path starts with /tmp instead of the repository or package directory.
Cause
A relative path is resolved from the process’s current working directory, not from the source file or Package.swift location. Apple’s Xcode 26.4 release notes state that test runners for unit-test targets without a host application are now consistently launched with a default working directory of /tmp from both Xcode and xcodebuild (Resolved Issue 162549425).
Code that previously worked only because the current directory happened to be the project root now looks for /tmp/.env:
let data = try Data(contentsOf: URL(fileURLWithPath: ".env"))
Affected configurations
- Xcode 26.4 or later
- A unit-test target with no host application, including many Swift Package tests
- Tests that load
.env, JSON, certificates, or fixtures through relative paths - Code that relied on the incidental working directory used before Xcode 26.4
Important: This does not mean that Xcode 26.4 broke Foundation file APIs. The Xcode change made test-runner behavior consistent and exposed an implicit dependency on the working directory. Reinstalling Xcode or deleting DerivedData does not remove that dependency.
Recommended fix
1. Confirm the working directory
print("cwd:", FileManager.default.currentDirectoryPath)
If the failing test prints /tmp, compare that with the absolute path in the error. This separates the Xcode 26.4 behavior change from a missing target-membership or permissions problem.
2. Put fixtures in the test bundle
For an Xcode project, add fixtures to the test target and resolve them from its bundle:
final class ResourceAnchor {}
let bundle = Bundle(for: ResourceAnchor.self)
let url = try XCTUnwrap(
bundle.url(forResource: "sample", withExtension: "json")
)
let data = try Data(contentsOf: url)
Also verify Test Target Membership and the test target’s Copy Bundle Resources phase.
3. Use Swift Package resources and Bundle.module
// Package.swift
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"],
resources: [.copy("Fixtures")]
)
// Test code
let url = Bundle.module.url(
forResource: "sample",
withExtension: "json",
subdirectory: "Fixtures"
)!
This approach works regardless of whether the test starts in Xcode, xcodebuild, or CI.
4. Pass secrets through the environment
Do not copy API keys or other secrets into a test bundle. Configure them in the scheme or CI secret store and read them through ProcessInfo:
guard let apiBaseURL =
ProcessInfo.processInfo.environment["TEST_API_BASE_URL"] else {
throw XCTSkip("TEST_API_BASE_URL is not configured")
}
Alternatives
If an existing loader cannot be changed immediately, pass the repository or configuration-file path explicitly through an environment variable and construct an absolute URL:
let env = ProcessInfo.processInfo.environment
let root = try XCTUnwrap(env["TEST_PROJECT_ROOT"])
let envURL = URL(fileURLWithPath: root)
.appendingPathComponent(".env")
Changing the process directory with FileManager.default.changeCurrentDirectoryPath(...) can be a temporary compatibility measure, but it introduces shared process state and can interfere with parallel tests. Bundle resources or explicit URLs are safer long-term solutions. Downgrading to Xcode 26.3 is also only a temporary workaround.
How to verify the fix
- Run the affected unit test in Xcode 26.4.
- Run the same test with
xcodebuild test. - Confirm that the log no longer resolves the resource to
/tmp/.env. - Verify resource loading both locally and in CI.
- Confirm that secrets were not copied into the test bundle or committed to source control.
Cautions
- Application-hosted unit tests and UI tests run in different processes and may require different resource lookup rules.
- A path reconstructed from
#filePathmay work locally but is fragile in CI and packaged test bundles. - Do not solve the problem by permanently placing configuration files in
/tmp; parallel tests can collide and secrets can remain on disk. - There is no later “fixed version” for this behavior. Xcode 26.4 itself contains the resolved issue that makes the default directory consistent between Xcode and
xcodebuild.
Summary
No such file or directory: /tmp/.env in Xcode 26.4 usually means that a hostless unit test depended on the previous incidental working directory. Load fixtures from the test bundle or Bundle.module, and provide secret configuration through environment variables or another explicit path.
Official references
- Apple Developer: Xcode 26.4 Release Notes (Resolved Issue 162549425)
- Apple Developer: Bundle
- Apple Developer: XCTest
