This error occurs when CircleCI cannot authenticate to your Git repository because the SSH checkout key has been deleted, revoked, or is misconfigured. The fix involves regenerating or adding a new deploy key in both CircleCI and your Git hosting provider.
This error indicates that CircleCI's automated checkout step failed because the SSH key it uses to authenticate with your Git repository (GitHub, GitLab, Bitbucket) is no longer valid. CircleCI uses SSH deploy keys to clone your repository at the start of each build. When you see "Permission denied (publickey)" followed by the CircleCI-specific message about the checkout key being invalid or revoked, it means the SSH key pair has become out of sync. This typically happens when: 1. Someone deleted the deploy key from your GitHub/GitLab/Bitbucket repository settings 2. The SSH key was regenerated in CircleCI but not updated in the repository 3. The repository was transferred to a different organization or user 4. Access permissions to the repository changed The checkout step is one of the first things CircleCI does in a pipeline, so this error will cause your entire build to fail immediately before any tests or deployments can run.
First, verify what SSH keys CircleCI is currently using for your project:
1. Go to your CircleCI project dashboard
2. Click Project Settings (gear icon)
3. Navigate to SSH Keys in the left sidebar
4. Look at the Checkout SSH Keys section
You'll see one of these key types:
- Deploy Key: Repository-specific, read-only access (recommended)
- User Key: Uses your personal GitHub account permissions
Note the Fingerprint shown - you'll need this to match it with GitHub.
If no checkout key is listed, that's the problem - continue to step 3 to add one.
Check if the corresponding public key exists in your repository:
For GitHub:
1. Go to your repository on GitHub
2. Click Settings > Deploy keys
3. Look for a key with fingerprint matching CircleCI's key
For GitLab:
1. Go to your project on GitLab
2. Click Settings > Repository > Deploy Keys
3. Verify the CircleCI key is listed and enabled
For Bitbucket:
1. Go to your repository on Bitbucket
2. Click Repository settings > Access keys
3. Check if the CircleCI key exists
If the key is missing from your repository but exists in CircleCI, the key needs to be re-added. Continue to step 4.
If CircleCI has an outdated or invalid key, remove it:
1. In CircleCI, go to Project Settings > SSH Keys
2. Under Checkout SSH Keys, find the problematic key
3. Click the X or Delete button next to the key
4. Confirm the deletion
Note: This will temporarily break builds until you add a new valid key.
Alternatively, use the CircleCI CLI or API:
# Using CircleCI CLI (if installed)
circleci project settings --delete-checkout-key <fingerprint>Generate and add a new checkout key:
Option A: Let CircleCI generate the key (Recommended)
1. In CircleCI, go to Project Settings > SSH Keys
2. Scroll to Checkout SSH Keys
3. Click Add Deploy Key (or Create and add key)
4. CircleCI will automatically:
- Generate a new SSH key pair
- Add the public key to your GitHub repository as a deploy key
- Configure the private key for use in builds
Option B: Add a User Key (for private dependencies)
If your build needs to access multiple private repositories:
1. Click Add User Key instead
2. Authorize CircleCI to access your GitHub account
3. This grants access to all repositories your account can access
Warning: User keys have broader access. Prefer deploy keys for single-repository access.
For GitLab or Bitbucket:
CircleCI may not auto-add keys for non-GitHub repos. You'll need to:
1. Generate a key pair manually
2. Add the private key to CircleCI
3. Add the public key to your GitLab/Bitbucket repository
For GitLab, Bitbucket, or self-hosted Git:
Generate a new SSH key pair:
# Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "circleci-deploy@your-project" -f circleci_key -N ""
# Or generate an RSA key for older systems
ssh-keygen -t rsa -b 4096 -C "circleci-deploy@your-project" -f circleci_key -N ""This creates two files:
- circleci_key (private key)
- circleci_key.pub (public key)
Add the private key to CircleCI:
1. Go to Project Settings > SSH Keys
2. Click Add SSH Key under "Additional SSH Keys"
3. Enter your Git hostname (e.g., gitlab.com, bitbucket.org)
4. Paste the contents of circleci_key (private key)
5. Click Add SSH Key
Add the public key to your repository:
# Display the public key
cat circleci_key.pubCopy this and add it as a deploy key in your repository settings.
Securely delete the local key files:
rm circleci_key circleci_key.pubAfter adding the new key, trigger a new build:
1. Go to your CircleCI project dashboard
2. Click Rerun workflow from failed or Rerun from start
3. Watch the Checkout code step
Expected success:
Checkout code
Using SSH Config
Cloning into '.'...
done.If it still fails, check:
- The key fingerprint matches between CircleCI and your repository
- The deploy key has read access to the repository
- For private repos, ensure the key is not read-only if write access is needed
Verify SSH connectivity manually:
You can also test from a CircleCI shell:
# Add this step temporarily to your config.yml
- run:
name: Debug SSH
command: |
ssh -T [email protected] || true
ssh-add -lFor repositories in a GitHub Organization, additional steps may be required:
Enable OAuth App access:
1. Go to your GitHub Organization settings
2. Navigate to Third-party access > OAuth Apps
3. Find CircleCI and click Review
4. Ensure CircleCI has access to the repository
Request organization approval (if required):
If your organization restricts third-party access:
1. An organization admin must approve CircleCI's access
2. The admin can do this at: Organization Settings > Third-party access
Use SSH deploy keys instead of OAuth:
For stricter security requirements, use deploy keys:
1. Remove any user keys in CircleCI
2. Add a deploy key as described in step 4
3. Deploy keys are scoped to a single repository
Check organization SAML enforcement:
If your organization uses SAML SSO:
1. Ensure your SSH keys are authorized for SAML
2. Go to GitHub Settings > SSH and GPG keys
3. Click Configure SSO next to the relevant key
4. Authorize the key for your organization
If using a custom SSH key (not the default checkout key), update your .circleci/config.yml:
Using the add_ssh_keys step:
version: 2.1
jobs:
build:
docker:
- image: cimg/base:stable
steps:
# Add custom SSH key before checkout
- add_ssh_keys:
fingerprints:
- "SO:ME:FI:NG:ER:PR:IN:T0:12:34:56:78:90:ab:cd:ef"
# Now checkout will use the added key
- checkout
- run:
name: Build
command: echo "Building..."For accessing private dependencies:
steps:
- add_ssh_keys:
fingerprints:
- "key-fingerprint-for-private-dep-repo"
- checkout
- run:
name: Clone private dependency
command: git clone [email protected]:org/private-lib.gitFind the fingerprint:
The fingerprint is shown in CircleCI under Project Settings > SSH Keys after you add the key.
### Debugging SSH Issues in CircleCI
Add debugging steps to your config to diagnose SSH problems:
- run:
name: Debug SSH Configuration
command: |
echo "=== SSH Keys loaded ==="
ssh-add -l
echo "=== SSH Config ==="
cat ~/.ssh/config || echo "No SSH config"
echo "=== Testing GitHub SSH ==="
ssh -vT [email protected] 2>&1 || true
echo "=== Known Hosts ==="
cat ~/.ssh/known_hosts || echo "No known hosts"### Deploy Keys vs User Keys
| Feature | Deploy Key | User Key |
|---------|-----------|----------|
| Scope | Single repository | All repos user can access |
| Security | More restricted | Broader access |
| Setup | Per repository | Once per user |
| Use case | Single repo CI/CD | Multi-repo access |
| Revocation | Remove from repo | Remove from user account |
Best practice: Use deploy keys unless you specifically need access to multiple private repositories.
### Rotating SSH Keys
Periodically rotate your CircleCI SSH keys for security:
1. Generate a new key pair
2. Add the new key to CircleCI and your repository
3. Verify builds work with the new key
4. Remove the old key from both CircleCI and your repository
### Self-Hosted Git Servers
For self-hosted Git (GitHub Enterprise, GitLab self-managed):
# .circleci/config.yml
- add_ssh_keys:
fingerprints:
- "your-key-fingerprint"
- run:
name: Add self-hosted Git to known hosts
command: |
mkdir -p ~/.ssh
ssh-keyscan git.yourcompany.com >> ~/.ssh/known_hosts### SSH Key Fingerprint Format Changes
CircleCI may show fingerprints in different formats:
- MD5: ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90
- SHA256: SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
To convert between formats:
# Get MD5 fingerprint
ssh-keygen -l -E md5 -f your_key.pub
# Get SHA256 fingerprint
ssh-keygen -l -E sha256 -f your_key.pub### CircleCI Contexts and SSH Keys
If using CircleCI Contexts for shared secrets:
1. You cannot store SSH keys in Contexts directly
2. SSH keys must be added at the project level
3. For multiple projects needing the same key, add it to each project
### Common Misconfigurations
Wrong hostname in SSH key:
Ensure the hostname in CircleCI matches exactly:
- github.com (not www.github.com)
- gitlab.com (not https://gitlab.com)
Read-only deploy key for push operations:
If your CI needs to push (e.g., release tags):
1. When adding the deploy key to GitHub, check Allow write access
2. Or use a user key instead
Key added to wrong repository:
For forked repositories, ensure the key is added to the correct repo (fork vs upstream).
### Monitoring Key Health
Set up alerts for SSH authentication failures:
# Notify on checkout failures
- checkout:
post-checkout:
- run:
name: Verify checkout
command: |
if [ ! -f "package.json" ]; then
echo "Checkout may have failed"
exit 1
fi### Related CircleCI Errors
- "Host key verification failed" - Add the host to known_hosts
- "fatal: Could not read from remote repository" - SSH key issue
- "ERROR: Repository not found" - Wrong key or missing repo access
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git