Fix Git LFS errors — smudge filter failed and pointer files
Git LFS is broken — my files are text pointers, or the clone dies with 'smudge filter lfs failed'
If you’re seeing this error
Encountered 1 file(s) that should have been pointers, but weren'terror: external filter 'git-lfs filter-process' failedfatal: <file>: smudge filter lfs failedbatch response: This repository is over its data quota.You’re in the right place — the fix is below.
Short answer
A smudge failure means Git downloaded the pointer files but could not fetch the real content. Clone with GIT_LFS_SKIP_SMUDGE=1 to get past it, run git lfs install to register the filters, then git lfs pull to fetch the actual bytes. If you are seeing a 130-byte text file where a binary should be, the pointer was never expanded — the content is safe on the server.
git lfs install
git lfs pull
# clone that keeps failing:
GIT_LFS_SKIP_SMUDGE=1 git clone <url> && cd <repo> && git lfs pull
Register the filters, then fetch the real content separately
Does this match your situation?
- 'fatal: <file>: smudge filter lfs failed' during clone, pull or checkout.
- An image or binary opens as three lines of text starting 'version https://git-lfs.github.com/spec/v1'.
- 'batch response: This repository is over its data quota.'
- 'Encountered 1 file(s) that should have been pointers, but weren't'
- Everything works for you and breaks for a colleague who does not have LFS installed.
Step-by-step fix
Confirm LFS is actually installed and registered
Installing the git-lfs binary is only half the job. git lfs install writes the clean and smudge filter configuration into your global Git config — without it, Git happily checks out the pointer text and considers the job done.
step 1git lfs version git lfs install git config --get filter.lfs.smudgegit lfs install is per-user, not per-repository. A new machine, a new container or a fresh CI image needs it again.
Get past a clone that will not finish
Skipping the smudge filter tells Git to check out the pointer files and move on, so the clone completes even if the LFS server is unreachable, rate-limited or out of quota. You then fetch the content as a separate, retryable step.
step 2GIT_LFS_SKIP_SMUDGE=1 git clone <url> cd <repo> git lfs pullShow the Windows / PowerShell version
Windows / PowerShell$env:GIT_LFS_SKIP_SMUDGE = "1" git clone <url> cd <repo> git lfs pull Remove-Item Env:\GIT_LFS_SKIP_SMUDGEReplace pointer files with real content
If your working tree already contains pointer text, git lfs pull downloads the objects and rewrites those files in place. Nothing is lost — the pointer is just an address, and the bytes it points at live on the LFS server.
step 3git lfs pull git lfs checkout # re-expand pointers already in the tree git lfs statusDiagnose which side is failing
The smudge filter fails for three unrelated reasons: authentication, quota, and corruption. This is how you tell them apart before you start changing things.
step 4GIT_TRACE=1 GIT_CURL_VERBOSE=1 git lfs pull 2>&1 | head -40 git lfs env git lfs fsckA 401 or 403 means credentials; 'over its data quota' means bandwidth or storage on the host; anything else usually means a damaged local cache.
Clear a corrupted local LFS cache
Half-downloaded objects in .git/lfs/objects cause the filter to fail on files that pull perfectly well on another machine. Pruning them forces a clean re-download.
step 5git lfs prune rm -rf .git/lfs/objects git lfs fetch --all git lfs checkoutFix binaries that were committed without LFS
'Files that should have been pointers, but weren't' means real binary content was committed while LFS tracking was in place — usually by someone whose client had no LFS installed. Migrating rewrites those commits to use pointers.
step 6git lfs track "*.psd" git add .gitattributes # convert existing history (rewrites commits - coordinate with your team): git lfs migrate import --include="*.psd" --everythinggit lfs migrate rewrites history and requires a force-push. Everyone else must re-clone or reset to the new history afterwards.
Why this works
Git LFS is not part of Git. It is a pair of filters Git calls on the way in and out: the clean filter replaces a large file with a small text pointer before it is committed, and the smudge filter swaps that pointer back for the real bytes on checkout. What Git stores and transfers is the pointer — a hundred-odd bytes naming a SHA-256 and a size — while the content travels over a completely separate HTTP API with its own authentication and its own quota. So 'smudge filter lfs failed' never means your repository is damaged. It means Git got the pointers and the second, independent download did not happen, which is why every fix is about that second channel rather than about Git itself.
If that didn’t work
- Check the host's LFS quota page — GitHub bills storage and bandwidth separately, and both stop downloads when exhausted.
- Re-authenticate: git credential reject, then retry, so a stale token is not being replayed.
- Try over SSH rather than HTTPS, or the reverse — LFS negotiates its endpoint from the remote URL.
- On CI, confirm the checkout step enables LFS explicitly (actions/checkout needs lfs: true).
How to stop it happening again
- Set up git lfs track before the first commit of any binary — migrating afterwards means rewriting history.
- Commit .gitattributes in the same commit as the tracking rule, so everyone else picks it up automatically.
- Add git lfs install to your project's setup instructions; it is per-machine and easy to forget.
- Watch the quota on hosted plans — 1 GB of free bandwidth disappears fast on a repository full of textures.
Commands used in this guide
git lfsStore large binary files outside history and keep the repo small.
.gitattributesPer-path rules for line endings, diffing, merging and export.
git cloneCopy a remote repository, its full history and its branches, onto your machine.
git configRead and write Git settings for one repo, your user, or the whole machine.
git credential / credential.helperStop Git asking for your username and password on every push.
Still stuck?
Search the full command reference and every other rescue guide — there are 76 of them, covering everything from detached HEAD to force-push disasters.
Browse all guides →Frequently asked questions
What does 'smudge filter lfs failed' mean?
Git checked out a file tracked by LFS and asked git-lfs to swap the pointer for the real content, and that request failed. The usual causes are LFS not being installed on your machine, an authentication failure against the LFS API, an exhausted bandwidth quota, or a corrupted local cache in .git/lfs/objects.
Why is my image file just text starting with 'version https://git-lfs.github.com'?
That is the LFS pointer, checked out raw because the smudge filter never ran. Your real file is unharmed on the server. Run git lfs install then git lfs pull, and the pointers are replaced with the actual bytes in place.
How do I clone a repository when LFS keeps failing?
GIT_LFS_SKIP_SMUDGE=1 git clone <url>. Git checks out the pointers, the clone completes, and you then run git lfs pull inside the repository as a separate step you can retry as often as you need.
What does 'This repository is over its data quota' mean?
The host has stopped serving LFS objects because the repository exhausted its storage or, more often, its monthly bandwidth allowance. GitHub gives 1 GB of each for free. Nothing is lost — buy a data pack, wait for the monthly reset, or move the assets to a different store.
Can I remove Git LFS from a repository?
Yes — git lfs migrate export --include="*.psd" --everything pulls the real content back into ordinary Git objects and removes the pointers. It rewrites history, so it needs a force-push and a re-clone from everyone, and your repository will grow to the full size of every version of those binaries.
Related rescue guides
I committed a large file and my push is rejected — how do I remove it?
If it's still the last commit, git reset --soft HEAD~1 and re-commit without it. If it's further back, purge it from history with git filter-repo --strip-blobs-bigger-than. Going forward, route large binaries through Git LFS.
Read the fix →Always fixableMy .git folder is enormous — how do I find the biggest files in history?
git count-objects -vH tells you the total size; combining git rev-list --objects with git cat-file --batch-check lists the largest blobs by name. Deleting the files now won't shrink anything — they have to be purged from history.
Read the fix →Always fixableCloning takes forever — how do I clone a big repo faster?
Use --filter=blob:none for a partial clone that fetches file contents lazily, and add sparse-checkout to materialise only the directories you need. --depth 1 is fastest of all but gives you no usable history.
Read the fix →Always fixableCloning or pushing dies with 'RPC failed' or 'the remote end hung up unexpectedly' — how do I get it through?
The connection dropped part-way through a large transfer. Nothing is damaged. Clone shallow to make the transfer small enough to finish (git clone --depth 1), then deepen it with git fetch --unshallow. Switching the remote to SSH avoids the HTTP layer entirely and fixes most stubborn cases.
Read the fix →