GitHub removed account-password authentication for Git operations on 13 August 2021. Your password is not wrong — it is no longer a credential. Replace it with a personal access token over HTTPS, or an SSH key, and clear whatever cached the old password.
This error confuses people because everything about it looks like a typo. The username is right, the password is right, and the message says authentication failed. Nothing is broken. The rule changed, and your credential helper is still cheerfully replaying a secret the server stopped honouring years ago.
There are two real fixes and one cleanup step. Pick the fix that matches how you clone, then do the cleanup, because the cached credential is the reason people fix this twice.
Table of contents
- What the error is actually telling you
- Fix one: a personal access token over HTTPS
- Fix two: SSH keys, which stop expiring
- The cached password that keeps coming back
- CI, containers, and anything without a human at the keyboard
- How this fits the rest of the stack
- FAQ
What the error is actually telling you
The full message usually looks like this:
remote: Invalid username or token.
Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/user/repo.git/'
Read the first line carefully. It says username or token — not username or password. The server is telling you which credential types it still accepts, and the account password is not one of them.
This applies to HTTPS remotes only. If your remote starts with https://, Git prompts for a username and password, and whatever it sends as the password must be a personal access token. If your remote starts with git@, you are on SSH and this error means something else entirely — usually a missing or unloaded key.
Check which one you are on before doing anything else:
git remote -v
# https://github.com/user/repo.git -> HTTPS, needs a token
# [email protected]:user/repo.git -> SSH, needs a key
The same change rolled through the other hosts on roughly the same timeline, so the fix generalises even when the wording of the error does not.
Fix one: a personal access token over HTTPS
This is the smaller change and the right one if you are already on HTTPS remotes and do not want to touch your SSH setup.
Generate a token in your account settings under developer settings, then use it as the password at the prompt. The username stays your normal username. Two things matter when you create it: the scopes and the expiry.
- For pushing and pulling private repositories,
repois the scope you need. Fine-grained tokens want read and write on Contents. - For pushing packages or triggering workflows, you need those scopes explicitly — a
repotoken will not cover them. - Expiry is a real trade. A 90-day token means this breaks again in 90 days. A no-expiry token means a leaked token is permanent.
Test it without committing anything first:
git ls-remote https://github.com/user/repo.git
# username: your-username
# password: ghp_xxxxxxxxxxxxxxxxxxxx
If that returns refs, the token works and the problem is now purely about where the credential is stored.
Resist the shortcut of embedding the token in the remote URL. It works, and it writes your token in plaintext into .git/config, where it will be read by every tool that walks the repo and copied by every clone-and-zip you do.
Fix two: SSH keys, which stop expiring
If you push several times a day, SSH is the better answer. No token rotation, no prompt, and no credential sitting in a config file.
ssh-keygen -t ed25519 -C "[email protected]"
cat ~/.ssh/id_ed25519.pub # paste into GitHub > Settings > SSH keys
ssh -T [email protected] # should greet you by username
Then point the existing repository at the SSH remote instead of the HTTPS one:
git remote set-url origin [email protected]:user/repo.git
Use ed25519 rather than RSA unless you have a specific reason. It is shorter, faster, and has been the sensible default for years.
If ssh -T hangs or gets refused, your network is probably blocking port 22. GitHub serves SSH over 443 as well, which gets through most corporate firewalls:
Host github.com
Hostname ssh.github.com
Port 443
User git
Put that in ~/.ssh/config and try again.
The cached password that keeps coming back
This is the step people skip, and it is why the error reappears an hour after they fixed it. Your credential helper stored the old password, and it keeps sending it without prompting you.
Find out which helper is active:
git config --list --show-origin | grep credential
Then clear the entry for the host:
- Windows — open Credential Manager, Windows Credentials, and delete the
git:https://github.comentry. - macOS —
git credential-osxkeychain erase, then typehost=github.com,protocol=https, and a blank line. - Linux with the store helper — the credentials are plaintext in
~/.git-credentials. Edit or delete the line. - Cache helper —
git credential-cache exitdrops it immediately.
After clearing, the next Git operation prompts again, and this time you paste the token. If it does not prompt, something is still caching — check for a second helper configured at system scope.
CI, containers, and anything without a human at the keyboard
An interactive prompt is not available in a build. Automated environments need the credential injected, and the shape of that differs by platform.
Inside GitHub Actions, the checkout action already handles this with the workflow token — you rarely need to supply anything:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
Elsewhere, pass the token as an environment variable and never as a literal in the file:
git clone https://x-access-token:${GIT_TOKEN}@github.com/user/repo.git
The important part is that GIT_TOKEN arrives from the platform’s secret store, not from the repository. A token committed to a Dockerfile is a token you will be rotating under pressure at some point.
For deploy pipelines specifically, a deploy key scoped to one repository is stronger than a personal token that can reach everything you can reach. If the build only needs to read one repository, give it exactly that.
How this fits the rest of the stack
Git credentials are a small instance of a general problem: something your build needs, that must not live in the repository. Tokens, database URLs, API keys and signing secrets all have the same shape, and the answer is the same — the platform holds them, the build reads them at runtime, and nothing sensitive is ever committed.
On RunxBuild that is what environment variables are for. You connect a GitHub repository, the build gets a token scoped to the deploy, and your secrets are set per service rather than baked into an image. If you are working out what a project costs once the service, the database and the storage are all running, the RunxBuild hosting calculator shows the line items side by side rather than as one number at the end of the month.
Useful related references:
- SSH: No Supported Authentication Methods Available (Server Sent Publickey)
- The Jira REST API: Authentication, Search, and the Pagination Trap
- Error Logs: The Part That Is the Operations Truth, and the Part That Is Just Noise
- Services on RunxBuild
FAQ
Why did GitHub remove password authentication?
Passwords are reused across sites and rarely have scopes. A leaked password gives an attacker everything the account can do, indefinitely. A token can be limited to specific permissions, restricted to specific repositories, expired on a schedule and revoked on its own without touching the account. The change was announced in December 2020 and enforced from 13 August 2021.
Is a personal access token the same thing as my password?
No, and treating it like one is the mistake. A token is a separate credential with its own scopes and its own expiry, and revoking it does not affect your account login. You can hold several tokens for different machines and kill just the one on the laptop you lost.
Should I use HTTPS with a token, or SSH?
SSH if you push often from a machine you control, because there is nothing to rotate. HTTPS with a token if you are on a locked-down network, in a container, or in CI, because it needs no key material on disk. Both are fully supported and neither is going away.
I fixed it and the error came back the next day. Why?
A credential helper still holds the old password and is replaying it before you get a prompt. Clear the stored entry for the host in Windows Credential Manager, the macOS keychain, or ~/.git-credentials, then retry so Git asks you again.
Does this affect GitLab and Bitbucket too?
Yes, on their own timelines. Bitbucket Cloud moved to app passwords and then API tokens, and GitLab pushes personal access tokens for HTTPS. The wording in the error differs but the fix is the same shape: a scoped token or an SSH key instead of the account password.