The symptom: Xcode 26.6 reports package resolution errors, missing products, or unexpected dependency versions.
The fastest fix: lock Xcode, Package.resolved, and the resolver command first; then test the version graph, Git access, cache state, and execution environment separately. Do not erase every cache as your first move.
This guide is for you if an Xcode 26.6 upgrade broke package resolution, if a private Swift package works locally but fails on a Remote Mac, or if you maintain an unattended iOS build machine. It is also useful when a team sees dependency changes that nobody deliberately approved.
Last updated August 23, 2026. Xcode version status was checked against Apple’s Xcode release record and the Xcode 26.6 release notes.
Baseline evidence before any repair
A package-resolution failure is not the same as a compile failure. Xcode can resolve the dependency graph successfully and later fail while checking out source, linking a package product, compiling Swift, or creating an Archive. Your first task is to identify the failing state.
Capture these values with secrets removed:
- The Xcode version shown by the GUI and by the shell.
- The active developer directory from
xcode-select. - The repository commit.
- The project or workspace path.
- The selected scheme and configuration.
- The exact resolver command.
- The first useful error, not the final cascade of secondary errors.
- The relevant package names and repository hosts.
Use obvious placeholders in shared notes:
xcodebuild -version
xcode-select -p
git rev-parse HEAD
xcodebuild -resolvePackageDependencies \
-workspace "/PATH/TO/APP.xcworkspace" \
-scheme "APP_SCHEME"
Replace every path and scheme with your own values. Never paste a token, private hostname, username, SSH key, or full private repository URL into a ticket.
Run resolution through Xcode and through xcodebuild. If the GUI succeeds but the shell fails, investigate the Xcode session, shell environment, user account, and working directory. If both fail with the same first error, the project graph or repository access is more likely to be involved.
Keep the original log. Save the repaired log separately. A before-and-after comparison is more valuable than a claim that “clearing the cache fixed it.”
Version graph and lockfile state
Package.resolved is the most useful comparison point for an application build. It records the resolved package graph that the repository expects. Package.swift defines dependency requirements, while the project or workspace determines how those requirements are consumed. Apple documents dependency requirements such as exact, range-based, and branch-based rules in the Package.Dependency documentation.
Compare the three layers:
| Layer | What to inspect | Failure signal |
|---|---|---|
Package.swift |
URLs, identities, requirement rules, local package references | A pin no longer satisfies the declared requirement |
| Project or workspace | Package references, schemes, package products, local overrides | The expected product is not attached to the active target |
Package.resolved |
Package identity, location, revision, and version pins | Stale, duplicated, conflicted, or unexpected records |
For an application repository, commit Package.resolved when reproducible dependency selection matters. Review it with the source change that caused it. Do not treat a lockfile update as harmless housekeeping: it can alter transitive packages and package products even when the direct dependency is unchanged.
The boundary is different for a reusable library. A library can declare its requirements, but the consuming application normally owns the final resolved graph. Committing a library lockfile does not automatically make every consumer use those pins. This distinction prevents a common mistake: copying an application lockfile into a package repository and assuming it controls downstream builds.
Check branch and merge history next:
- Look for conflict markers or duplicated package records.
- Confirm that the lockfile belongs to the current project or workspace.
- Check whether an update script ran before the build.
- Compare the current package identities with the identities in the lockfile.
- Confirm that a branch switch did not leave a lockfile from another project state.
- Check whether a local package override is masking the remote package.
Swift Package Manager describes version resolution and pin changes in its official resolution guide. Use that model to distinguish a legitimate graph update from a broken or stale record.
Git access across public and private packages
A public package and a private package can fail at different layers. Do not label every message “a network issue.” Identify whether the failure occurs during name lookup, connection, authentication, host verification, repository authorization, or object download.
| Access layer | Public package check | Private package check |
|---|---|---|
| URL | Confirm the repository URL and package identity | Confirm the URL without exposing it in logs |
| DNS and proxy | Test the host from the build machine | Test the private Git host from the same user |
| SSH | Confirm the transport actually used | Check key loading and known-hosts access |
| Authorization | Verify the repository still exists | Verify the build account has read access |
| Fetch | Compare the requested revision with the repository | Confirm the account can fetch that revision |
A local terminal may use your login shell, while an unattended job may use a different user and home directory. That changes access to:
~/.gitconfig~/.ssh/configknown_hosts- SSH agents
- credential helpers
- proxy variables
- certificate stores
xcodebuild may not read exactly the same Git configuration as the Git command you run interactively. Apple’s continuous integration guidance for Swift packages and apps is the appropriate reference for choosing a supported CI entry point and matching the project, scheme, and build context.
Use safe probes. For example, inspect the effective user and home directory, then test access to a redacted host. Do not print credentials:
whoami
printf '%s\n' "$HOME"
git config --show-origin --get-regexp 'url|credential|ssh' || true
ssh -G "git@GIT_HOST.example" | sed -E 's/(identityfile|user) .*/\1 [REDACTED]/'
A successful connection to the host does not prove repository permission. A successful authentication does not prove that the requested revision exists. Record the first failed stage.
Cache layers and controlled resets
“Clear the package cache” is too broad to be a diagnosis. Several storage areas can influence different stages of a build.
| Storage area | Typical role | What a reset can affect |
|---|---|---|
| Repository or package cache | Stores fetched package data and metadata | Forces network access and exposes Git failures |
| Dependency checkout directory | Holds checked-out package sources | Removes local source state and increases download work |
| DerivedData | Stores indexes, intermediate files, and build products | Forces recompilation and may hide unrelated build issues |
| Archive and export output | Stores distributable build results | Deletes evidence needed for release comparison |
Start with comparison, not deletion. If the existing cache resolves while a cold cache fails, the problem may be access or repository availability. If both paths fail with the same revision error, cache removal is unlikely to be the real fix.
Before deleting anything, record:
- The path.
- Its approximate size if useful to your cleanup decision.
- Whether another job is using it.
- Whether it contains build artifacts needed for comparison.
- Whether recovery requires another fetch or a full rebuild.
Do not remove signing certificates, provisioning profiles, keychain items, or other signing material as part of package troubleshooting. Those belong to the signing layer, not the package cache layer.
Apple’s common Xcode configuration and build issue guidance supports separating configuration errors from later build errors. Apply that principle here: reset one layer, rerun the same resolver command, and record whether the first error changed.
Dependency products after successful resolution
A green resolver result does not guarantee a successful build. Keep these states separate:
- Dependency graph resolution.
- Source checkout.
- Dependency graph generation inside the project.
- Package product linkage.
- Swift or Objective-C compilation.
- Archive and export.
The most misleading example is missing package product. If the package repository was fetched successfully, investigate package identity, product declarations, target membership, scheme selection, and local package overrides before changing DNS or deleting caches.
Check the following:
- The product name matches the package’s declared product.
- The target links the product in the active configuration.
- The scheme includes the target that declares the package dependency.
- A local package has not replaced the remote package unexpectedly.
- A binary target has the expected checksum and supported artifact.
- The selected branch or commit contains the requested product.
- The error is reproducible in the same scheme used for Archive.
For binary dependencies, use Apple’s documentation on identifying binary dependencies. A package can resolve while its binary artifact later fails validation or integration. That is a different repair path from a Git fetch failure.
A minimal reproduction is the fastest way to separate project structure from environment state. Create a small test project that references the same package revision and product. Use the same user, developer directory, and command. If the minimal project succeeds, inspect the original workspace, target membership, and scheme. If it fails identically, return to access, version, or host configuration.
Remote Mac execution differences
A Remote Mac can make a local-looking failure reproducible, but only if the environment is treated as part of the build input. The source commit alone is not enough. Capture the Xcode selection, user, home directory, package lockfile, Git configuration, SSH configuration, and workspace path.
| Build input | Interactive local session | Unattended Remote Mac job | Required comparison |
|---|---|---|---|
| Developer directory | Selected by the logged-in developer | Selected by the job environment | Same Xcode path |
| User and home | Your account and home directory | Service or automation account | Same readable credentials |
| Git and SSH | Agent and personal configuration | Job-specific configuration | Same host and repository access |
| Workspace state | Existing checkout and caches | Clean or persistent checkout | Same commit and lockfile |
| Resolver command | GUI action or shell command | Scripted command | Same project, scheme, and options |
A Remote Mac build should first reproduce the repository’s committed lockfile. Avoid allowing every job to select newer package versions. Dependency updates should happen in a deliberate change, pass review, and produce a new lockfile.
For repeatability, run the same command after:
- A clean checkout.
- A package-cache reset.
- A host restart.
- A new job under the normal automation account.
- A normal build.
- An Archive using the release scheme.
The goal is not one successful run. The goal is recovery after the conditions that commonly expose hidden state.
You can review MACCOME’s available Remote Mac environment when your local machine cannot provide a stable macOS session for this validation. Treat it as a test environment first. Resolve packages, build the real project, and create an Archive before moving a recurring pipeline.
Decision branches for repair
Use these conditions instead of applying the same cleanup command to every incident:
- If the GUI and
xcodebuilddisagree, choose the shell command used by CI as the primary baseline. Compare the active developer directory, user, environment, and project path before touching caches. - If
Package.resolvedconflicts with declared requirements, choose a deliberate lockfile repair. Review the resulting graph, commit it, and rerun resolution from a clean checkout. - If public packages work but private packages fail, choose Git access investigation. Check DNS, proxy, SSH host verification, key loading, and repository permission in the build user’s context.
- If a cold cache fails but the warm cache works, choose access or repository investigation before cache deletion. The cache is evidence that the graph can resolve under some conditions.
- If resolution succeeds but a product is missing, choose project and package-product investigation. Do not retry network cleanup.
- If local and Remote Mac results differ, choose execution-context comparison. Reproduce with the same user, home directory, lockfile, command, and developer directory.
- If the same repository fails after controlled resets, choose a minimal reproduction. Rebuild the environment only after the failure remains stable and attributable to the host.
This branch structure also clarifies when a Remote Mac is justified. If your local machine lacks a persistent macOS environment, or if the build user cannot retain the required checkout and credentials safely, a hosted machine can provide a cleaner baseline. If the issue is a malformed lockfile or invalid package product, changing hosts will not repair the project.
Environment acceptance for unattended builds
Use a repeatable acceptance record rather than a single green build. The record should include the repository commit, the exact Package.resolved, the selected Xcode path, the automation user, the resolver output, and the Archive result.
| Acceptance check | Pass condition | Failure interpretation |
|---|---|---|
| Dependency resolution | Same lockfile resolves without an unexpected update | Version graph or access issue |
| Normal build | The selected scheme builds with the same inputs | Project, product, or compiler issue |
| Archive | The release scheme creates the expected archive | Signing, target, or release configuration issue |
| Restart recovery | The job works after the host restarts | Hidden session or temporary-state dependency |
| Clean checkout recovery | The job restores packages from the repository state | Cache or credential dependency |
| Unattended execution | The automation user completes the full path | User, SSH, Git, or keychain mismatch |
Keep logs from each stage, but redact repository URLs, account names, hostnames, tokens, and key paths. Compare the first meaningful error after each change. If the error moves from authentication to package-product linkage, that is useful progress: the access layer may now be repaired, and the next layer can be handled independently.
For a long-running build machine, separate dependency updates from release builds. A scheduled update job can produce a reviewed lockfile. The release job should consume that known state. This avoids a build becoming non-reproducible because a transitive package changed between two otherwise identical runs.
FAQ
Xcode cannot resolve a Swift Package dependency
Preserve the original error first. Record Xcode, the active developer directory, the repository commit, the project or workspace, and the resolver command. Compare GUI resolution with xcodebuild. Then inspect the lockfile, Git access, and cache layers in that order. A cache reset is a controlled experiment, not a substitute for identifying whether the failure is graph-related or environment-related.
Committing Package.resolved
For an application, commit Package.resolved when you need reproducible dependency selection across developers and CI. Review every pin change. For a reusable package, distinguish its declared requirements from the consuming application’s final graph. The application usually owns that final resolution. The important rule is consistency between the lockfile, package declarations, project references, and the build scheme.
Local success and Remote Mac failure
Check the execution user, home directory, SSH agent, known-hosts file, Git configuration, proxy variables, checkout path, and active developer directory. An interactive Xcode session may have credentials and caches that an unattended job cannot read. Run the same xcodebuild resolver command with the same committed lockfile on both systems. Compare the first failure stage rather than comparing only the final build status.
Fixing fixed Swift Package versions with xcodebuild
Use the committed Package.resolved as the baseline and avoid update actions in routine build jobs. Invoke resolution against the same project or workspace used for Archive. Review Package.swift and Package.resolved together whenever dependencies change. Apple’s CI documentation should guide the entry point, while the exact project path, scheme, and command options must match your repository.
Package Cache reset did not help
Move back to the failure layers. Verify repository access, SSH host verification, credentials, package constraints, package products, local overrides, binary checksums, and the active Xcode selection. Test a cold checkout and a warm checkout separately. If the same repository still fails under the same user and command, create a minimal reproduction. Rebuilding the host is reasonable only after the failure is attributable to the environment.
Choosing between the current setup and a Remote Mac
If your current setup depends on a developer’s logged-in session, loses package caches after cleanup, uses personal SSH credentials, or cannot recover after a restart, it is a weak unattended build baseline. Those weaknesses create repeatability problems, expose access configuration, and make a successful local build poor evidence for release readiness.
A Remote Mac is a better fit when you need a persistent macOS environment for real-project validation, xcodebuild resolution, and Archive testing without buying another dedicated machine. You can start with a Mac mini Remote Mac plan from MACCOME, validate the complete dependency path, and keep your current machine as a fallback while the evidence is collected.
The decision should follow the logs: fix the repository when the graph is wrong, fix credentials when private access fails, and move environments only when the host or execution context prevents a stable baseline.