Skip to content

Authentication troubleshooting

This page covers the recurring failure modes around credentials. For credential setup itself, see SSH keys or OAuth sign-in.

How the picker works

The clone screen (and the push/fetch surfaces) chooses a credential in roughly this order:

  1. If you've explicitly picked one for this operation, use it.
  2. Otherwise pick the credential whose Host matches the URL's host.
  3. If multiple match, pick the most recently added.
  4. If none match, the field shows "Select…" and Clone is gated off until you choose one or add a new one.

The picker shows all credentials on every host — it doesn't hide non-matches. This is deliberate: if you're trying to clone git@example.com:foo/bar and you only see github.com credentials in the picker, the answer isn't "tap around to find hidden options," it's "add a credential for example.com."

"No credentials yet"

You're seeing this either in the Authentication settings list or when you flipped "Require authentication" on in the clone screen. Either way, the fix is the same: tap Add credential and walk through one of the credential flows. See:

Transport mismatch

The clone screen says something like:

SSH credentials don't work with HTTPS URLs. Pick a PAT or OAuth credential for this host, or change the URL to ssh://… / git@host:owner/repo form.

Or vice versa. The cause: each git transport speaks its own authentication. SSH credentials only authenticate SSH connections; HTTPS credentials (PAT, OAuth) only authenticate HTTPS connections. They aren't interchangeable.

Two ways to fix:

  • Change the URL. Most hosts offer both forms; copy the other from the repo page. GitHub's "Code" button has an HTTPS / SSH toggle, for instance.
  • Add a credential for the other transport. If your repo is cloned via SSH and you'd rather push over HTTPS for some reason, add a PAT or OAuth credential for the same host and pick it for this clone.

See also: Cloning troubleshooting — covers the URL format side of the same problem.

Host mismatch

The picker chose a credential that's for a different host than the URL. Example: trying to clone git@gitlab.com:foo/bar while the only credential is for github.com.

The fix is to add a credential for the URL's host, then pick it explicitly in the credential picker. Adding a credential doesn't delete or affect the existing one.

"Could not resolve SSH key from Keychain"

You tap Test on the clone screen and get this error. The credential exists in the list but its private key isn't in the Keychain, or isn't readable.

Most common causes:

  • The credential was added on a different device and restored from a backup that didn't include the Keychain entry. iOS treats Keychain entries as device-bound by default.
  • iOS migrated the device between major OS versions in a way that invalidated the entry.

Fix: delete the credential from the list, then add it back. If you have the original private-key file, use the Import flow; otherwise generate a new keypair and update the public key on the host. See SSH keys.

"Could not resolve credential from Keychain"

Same shape, but for an HTTPS credential (PAT or OAuth token). Same fix: delete the credential and re-add it. For OAuth, this means re-running the sign-in flow.

Credential removal blocked

You tap the trash icon on a credential and the app refuses with a list of project names that depend on it. This happens when one or more projects have "auth required" set and point at this credential — removing it would leave those projects unable to authenticate on the next push/fetch.

Two ways forward:

  • Update each listed project to use a different credential. Project settings → Sync → Edit remote, change the credential.
  • Or open each listed project's sync settings and turn off "Require authentication" if you don't need it for that project (e.g. if it's a read-only public repo).

Once no project points at the credential, the delete will succeed.

When to pick SSH vs OAuth vs PAT

A short opinionated guide:

  • SSH — long-lived, works on every host, never expires. Slight setup cost (generate a key, paste it into the host). Best for power users; only choice for some self-hosted setups.
  • OAuth — fastest setup on hosts that support it. Token may expire (silently refreshed on supporting hosts). Easiest path for GitHub.com, GitLab, modern Gitea.
  • PAT — paste-a-string flow. Useful when you've already generated a token elsewhere (CI, scripts) or when OAuth isn't set up on the host. You have to remember to renew when the token expires.

You can hold credentials of all three types for the same host — the picker will let you choose per-operation.

See also

Last updated: