If an Xcode 27 remote build cannot fetch a private Swift package, first verify the repository URL, the macOS account running the job, and that account’s credential source; then confirm Package.resolved is present and tracked. Do not put a token in the repository or URL. Xcode Cloud and self-hosted Mac builds use different authorization paths, so follow the one that matches your build environment.
This runbook is for you if a private package resolves locally but fails during a remote Mac iOS build, if you maintain a self-hosted macOS runner, or if you are setting up private dependencies in Xcode Cloud.
Fastest useful distinction: a rejected repository request is not the same problem as an unreachable host, a changed dependency revision, or a Swift compiler error.
Start by locating the first failure
Treat the first failing operation as the diagnostic boundary. A red build status alone does not identify a credential problem. Open the build report or command-line log and find the earliest error related to package resolution, source checkout, or compilation.
For a command-line build, run the same project or workspace and scheme used by the real job, with the same working directory and macOS user. Apple documents xcodebuild -resolvePackageDependencies as a way to resolve a project’s package dependencies separately from the later build; see the Xcode command-line tool reference. Preserve the relevant output, but redact repository paths, usernames, tokens, and any credential-bearing text before sharing it.
| First useful evidence | Likely fault area | Next check |
|---|---|---|
| Repository host cannot be reached or resolved | Network, DNS, firewall, or incorrect host | Test connectivity from the runner and verify the configured host |
| Repository responds with an access or authentication error | URL permissions or credentials | Check the job’s account and credential source |
| Package resolves, but the selected revision differs from the expected one | Lock file, branch, tag, or resolution state | Compare the checked-out Package.resolved and dependency declaration |
| Packages resolve, then Swift compilation fails | Source or compiler compatibility | Inspect the compiler diagnostic; do not treat it as a repository-authentication failure |
Check the repository address and reachability
Compare the dependency source in the project, Package.swift, and the resolved dependency record. Confirm that the remote job is contacting the intended SSH or HTTPS address, not merely an address that works from your development machine. Apple’s documentation describes the source and requirement information used in a Swift package dependency declaration.
Then test the dimensions separately:
- Address: Does the remote job use the expected host and repository path?
- Reachability: Can that runner resolve the host and establish a connection?
- Repository and reference: Does the repository exist for that account, and does the requested branch, tag, or revision still exist?
- Authentication: If the server is reachable, does the credential used by the job have permission to read that repository?
git ls-remote <sanitized-repository-url> <branch-or-tag>
A successful connection to the host does not prove that the repository path is correct or that the requested reference exists. Likewise, switching from SSH to HTTPS is not a universal authentication fix: it changes the transport and may require a different credential setup. Change the URL only when you have evidence that the configured address is wrong or that your workflow intentionally uses another transport.
Verify which macOS account runs the job
A common difference between a successful local build and a failed remote one is the executing identity. Your interactive account may have a private key loaded in an SSH agent, trusted server host keys, and a Git configuration that the runner account does not have.
Record the account and execution context at the point where the build starts. Check the job definition, runner service configuration, and shell environment. On a self-hosted Mac, run the diagnostic command and the dependency-resolution command as the same user that launches the production build. A test performed in your logged-in desktop session does not prove that a launch agent or CI service can use the same credentials.
| Credential or setting | What to verify for the job account | Evidence to retain |
|---|---|---|
| SSH private key | The intended key is readable by the account and not exposed in logs | Key identifier or secure-store reference, never key contents |
ssh-agent | The job can reach the expected agent and has the required identity loaded | Sanitized agent status |
known_hosts | The account can validate the repository host without an interactive prompt | Sanitized host-key entry or managed trust configuration |
| Git configuration | The account’s effective settings match the intended transport and host | Selected configuration keys without embedded secrets |
| HTTPS credential | The job obtains a scoped credential through its approved secret mechanism | Secret reference and access scope, not token value |
The key must also be usable in a non-interactive job. An SSH configuration that relies on a prompt, an agent available only in a terminal session, or a host key accepted only by your desktop account can pass local tests and still fail in CI. If you modify shared Git configuration, record its previous state and limit the change to the required account or host.Do not print environment variables wholesale while debugging. Build environments often contain signing, source-control, or upload credentials unrelated to the failing package request.
Choose the authorization path for the build environment
Do not copy local SSH instructions into Xcode Cloud. Xcode Cloud has a source-control authorization flow for private dependencies. Apple’s instructions for making dependencies available to Xcode Cloud and its source-control setup documentation describe the platform-specific setup. For a connected account, follow Apple’s Xcode Cloud connection steps and verify access using the account and workflow that perform the build.
Self-hosted macOS CI is different. You manage the runner’s macOS identity and its access to the repository. Configure a credential for the build account through your approved secret-management process, and check SSH trust and Git settings for that same account. If Apple’s documentation indicates a system Git configuration is appropriate for your workflow, validate that behavior in the Xcode version and job environment you actually use. Do not assume every Xcode installation or runner uses the same Git behavior.
| Build environment | Authorization to check | Common false assumption |
|---|---|---|
| Xcode Cloud | The source-control authorization configured for the workflow | A local Mac key also grants the hosted workflow access |
| Self-hosted Mac runner | Credentials and host verification available to the runner’s macOS account | A developer’s interactive terminal proves the runner can authenticate |
| Local Xcode build | The logged-in user’s source-control setup | Local success proves the remote build has the same identity and settings |
Confirm the lock file before changing resolution behavior
Inspect Package.resolved in the remote checkout and confirm that the file is in the project location used by your workflow and included in version control. Apple’s Swift package CI guidance explains how resolved package versions support repeatable CI builds. Compare the resolved package identities and revisions with the intended state; do not infer a lock-file problem solely from a fetch failure.
| Lock-file evidence | What it tells you | Action |
|---|---|---|
| Expected file is present and matches the reviewed change | The job can use the committed resolution state | Continue investigating access or compilation |
| File is missing from the checkout or not tracked | The remote job may resolve dependencies without the expected committed state | Check project placement and version-control status, then commit the intended lock file |
| File is present but contains an unexpected revision | The committed dependency state differs from the build expectation | Review the change that updated resolution before rebuilding |
| Resolution succeeds, but compilation fails | Fetching is no longer the blocker | Diagnose the compiler or source error separately |
Repair credentials without creating a second incident
Before changing a secret, determine where it may have been exposed. Search reviewed configuration and recent logs for credential-bearing URLs, shell tracing, or scripts that echo environment values. Do not paste an actual token, private key, or unredacted remote URL into a build report or support request.
If a secret was committed or written to a log, removing the visible text is not enough. Treat the credential as exposed, revoke or rotate it through the system that issued it, and check whether repository history or retained logs still contain the old value. Limit the replacement credential to the read access needed for package retrieval; do not reuse a broad personal credential when a narrower option is available.
Before removing an SSH key, changing shared Git configuration, or clearing package caches, identify which jobs and projects depend on the current setting. Keep a rollback path that restores the previous non-secret configuration if the change blocks an unrelated build. Cache cleanup is appropriate only when evidence points to stale or inconsistent cached state; it cannot grant repository permission or make an unreachable host available.
Apple’s guidance on common Xcode configuration and build issues can help you separate setup problems from build failures. Use it alongside the actual first error in your job log, not as a reason to apply unrelated cleanup steps.
Re-run the job and record proof of repair
Use this decision checklist before closing the incident:
- [ ] The failing job’s actual repository URL matches the intended dependency source.
- [ ] The repository host is reachable from the build environment.
- [ ] The requested repository and branch, tag, or revision are available.
- [ ] You know which macOS account executes the self-hosted job, or which Xcode Cloud authorization applies.
- [ ] The job account can access the required credential without exposing it in output.
- [ ] SSH host verification and relevant Git settings are available to the job account, when the workflow uses SSH.
- [ ]
Package.resolvedis present in the remote checkout and matches the intended dependency state. - [ ] The resolution step succeeds before you treat a later Swift compiler error as resolved.
- [ ] Any exposed secret has been replaced, and the new credential has only the access the build needs.
If resolution still fails, compare the failing job with the last successful one: account, credential reference, repository address, and lock-file change. Change one verified cause at a time. That produces a clearer rollback and avoids turning a credential incident into an unexplained dependency update.
FAQ: Private package fetch failures
Why does local resolution work while the remote build fails?
Your local session may have credentials and trusted host keys that the job account lacks. Check the actual remote account and credential source, then test repository access from that context. If the repository is reachable but denies access, investigate authorization; if it cannot be reached, investigate the host, DNS, or network path before changing dependency versions.
How can xcodebuild fetch an SSH dependency on a self-hosted Mac?
Run the resolution command as the same macOS account that runs the production build. Confirm that the account can use its SSH key and agent, validate the host through known_hosts, and read the intended Git configuration. Test with a sanitized repository address and avoid interactive prompts. Keep private key contents and tokens out of shell output and CI logs.
Where should you grant private-package access in Xcode Cloud?
Use the source-control authorization settings documented for Xcode Cloud and the workflow’s connected account. Confirm that this account can read the private repository, then test the workflow itself. A credential configured on a self-hosted Mac does not carry over to Xcode Cloud, so diagnose the hosted authorization path separately from local SSH settings.
What should you do if Package.resolved is absent from the remote checkout?
Confirm that the lock file is in the location used by the project and is tracked in version control. Compare the remote checkout with the dependency state reviewed for the build. If the workflow requires repeatable versions, commit the intended file and rerun resolution. Do not force a fresh automatic resolution to hide a missing file or a separate authentication failure.
If you have confirmed that the repository is reachable, authorization works, and the lock file is correct, but your self-hosted runner still lacks a stable macOS environment, a dedicated remote Mac may simplify account and credential isolation. A general cloud runner can leave you managing host access, persistent SSH state, and macOS-specific setup; buying a Mac avoids remote-host variability but adds hardware ownership and maintenance. Neither option fits every team: if you need local peripherals or sustained, predictable use, an owned Mac may be better. If you only need a separate macOS build environment when required, review MACGPU’s remote Mac options and the available Mac plans, then compare their access and delivery details with your runner requirements before choosing.