Fix: Git LFS Smudge Filter Error
Quick Answer
Resolve Git LFS smudge filter errors by installing Git LFS, fixing credentials, resetting LFS hooks, and handling bandwidth or storage quota issues.
The Error
You run git clone, git pull, or git checkout on a repository that uses Git LFS and get:
Downloading path/to/largefile.bin (150 MB)
Error downloading object: path/to/largefile.bin (abc1234): Smudge error: Error downloading path/to/largefile.bin (abc1234def5678...): batch response: This repository is over its data quota. Account responsible for LFS bandwidth should purchase more data packs to restore access.
Encountered 1 file that should have been a pointer, but wasn't.
error: external filter 'git-lfs smudge -- %f' failed
fatal: path/to/largefile.bin: smudge filter lfs failedOr a shorter variant:
error: external filter 'git-lfs smudge -- %f' failed
fatal: largefile.psd: smudge filter lfs failed
warning: Clone succeeded, but checkout failed.Why This Happens
Git LFS (Large File Storage) works by replacing large files in your repository with small pointer files. When you check out a branch, a smudge filter runs automatically to download the actual large file content from the LFS server and replace the pointer with the real file. When this process fails for any reason, you get a smudge filter error.
Common causes:
- Git LFS is not installed. The
.gitattributesfile in the repository tells Git to use LFS filters, but thegit-lfsbinary is not on your system. Git tries to run a filter that does not exist. - LFS hooks are not initialized. Even if the binary is installed, running
git lfs installsets up the global Git hooks and filter configuration. Without this step, Git does not know how to invoke the smudge filter. - Authentication failure. The LFS server requires credentials and your stored credentials are missing, expired, or incorrect. This often happens after rotating personal access tokens or SSH keys.
- Bandwidth or storage quota exceeded. GitHub, GitLab, and Bitbucket impose limits on LFS storage and bandwidth. Once exceeded, the server rejects download requests.
- Corrupted LFS pointer files. Someone committed the actual binary content instead of a pointer file, or a pointer file got mangled during a merge conflict.
- Network issues or self-hosted LFS server downtime. The LFS endpoint is unreachable, returning HTTP errors, or timing out.
- CI/CD environment missing LFS. Build runners and containers often do not include Git LFS by default, so clones succeed but checkouts fail when the smudge filter runs.
Fix 1: Install Git LFS
The most common cause is simply not having Git LFS installed. Check first:
git lfs versionIf this returns “command not found,” install it:
macOS:
brew install git-lfsUbuntu/Debian:
sudo apt-get install git-lfsWindows:
Download the installer from git-lfs.com or use:
choco install git-lfsAfter installation, initialize the hooks globally:
git lfs installThis writes the necessary smudge and clean filter configuration to your global ~/.gitconfig. Then re-pull the LFS objects:
git lfs pullFix 2: Re-initialize LFS Hooks
If Git LFS is installed but the filters are not configured (for example, after a Git upgrade or profile reset), re-initialize:
git lfs install --forceThe --force flag overwrites any existing hook configuration. You can verify the filters are set up correctly by checking your Git config:
git config --global --list | grep filter.lfsYou should see output like:
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.required=trueIf any of these lines are missing, git lfs install did not complete properly. Run it again and check for error messages.
Fix 3: Pull LFS Objects Manually
If the clone completed but checkout failed (you see the “Clone succeeded, but checkout failed” warning), the repository is on disk but the LFS files are still pointer stubs. Pull them manually:
git lfs pullIf that fails, try fetching first and then checking out:
git lfs fetch --all
git checkout -- .The fetch command downloads LFS objects to your local cache without modifying the working tree. The checkout then replaces pointer files with the real content from the cache.
Fix 4: Fix Credential and Authentication Issues
LFS downloads use your Git credentials. If authentication is failing, the smudge filter gets a 401 or 403 response and fails. First, test your connection:
git lfs envThis prints the LFS endpoint URL, authentication method, and other diagnostic information. Look at the Endpoint line to see which server is being contacted.
For HTTPS remotes, make sure your credential helper is configured and your token is valid:
git config --global credential.helper storeThen trigger a credential prompt by pulling:
git lfs pullEnter your username and personal access token when prompted. For GitHub, use a personal access token with the repo scope, not your account password.
For SSH remotes, the issue might be with your SSH key. If your regular Git operations work but LFS fails, note that LFS often uses HTTPS even when the repo remote is SSH. Check the LFS endpoint:
git lfs env | grep EndpointIf it shows an HTTPS URL, your HTTPS credentials need to be valid even though you clone over SSH. You can force LFS to use SSH by setting:
git config lfs.url "[email protected]:user/repo.git/info/lfs"If you are running into SSH key issues in general, see our guide on fixing git permission denied (publickey) errors.
Pro Tip: If your LFS credentials keep expiring in a corporate environment, use a credential manager that caches tokens. On macOS,
git config --global credential.helper osxkeychainstores credentials in the system keychain. On Windows,git config --global credential.helper manager-coreuses the built-in Windows Credential Manager. This prevents smudge filter failures caused by expired session tokens.
Fix 5: Fix .gitattributes Configuration
The .gitattributes file tells Git which files should be tracked by LFS. If it is misconfigured or missing, you can get smudge errors. Check what your repository tracks:
git lfs trackThis lists the patterns from .gitattributes. A typical configuration looks like:
*.psd filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -textIf a file type is listed in .gitattributes but was committed directly to Git (not through LFS), you get a pointer mismatch. To find these files:
git lfs fsckThis scans for files that should be pointers but are not. If it finds problems, you need to fix them by re-tracking the files:
git rm --cached path/to/largefile.bin
git add path/to/largefile.bin
git commit -m "fix: re-track file through LFS"If you want to remove a file pattern from LFS tracking entirely:
git lfs untrack "*.bin"Then update .gitattributes accordingly.
Fix 6: Handle LFS Bandwidth and Storage Quota Limits
GitHub provides 1 GB of free LFS storage and 1 GB of monthly bandwidth per repository. GitLab provides 5 GB. When you exceed these limits, the server rejects LFS downloads and the smudge filter fails with a quota error.
Check your usage on GitHub at Settings > Billing > Git LFS Data. If you are over the limit, your options are:
- Purchase additional data packs. GitHub sells them in 50 GB increments.
- Reduce LFS usage. Remove large files that no longer need to be tracked:
git lfs migrate export --include="*.psd" --everythingThis rewrites history to remove the specified file types from LFS, converting them back to regular Git objects. Be careful: this rewrites commit hashes and requires a force push.
- Use a different LFS server. You can point your LFS storage to a self-hosted server or S3-compatible storage:
git config lfs.url "https://your-lfs-server.example.com/user/repo"Common Mistake: Deleting large files from the repository does not free LFS quota. LFS objects are stored by content hash, and old objects remain on the server until they are garbage collected. To actually reclaim space, you need to delete the files from all branches and tags, then contact your hosting provider to run garbage collection (GitHub does this automatically after a period, but GitLab may require manual intervention).
Fix 7: Skip Smudge Filters During Clone
If you do not need the actual large files immediately (for example, you only need the source code), you can clone without downloading LFS content:
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/user/repo.gitThis clones the repository with LFS pointer files instead of the actual content. The pointer files are small text files that look like:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345678Later, when you need specific files, pull them selectively:
git lfs pull --include="assets/textures/*"Or pull everything:
git lfs pullThis approach is especially useful when cloning large repositories where you only work on a subset of the LFS-tracked files. Game development repositories, for example, often contain gigabytes of textures and audio assets that a backend developer never needs. Skipping the smudge filter during clone saves significant time and bandwidth, and you can always pull individual directories on demand.
You can also make this the default behavior for a specific repository by configuring it locally:
git config lfs.fetchexclude "assets/audio/*,assets/video/*"This tells LFS to skip downloading files matching those patterns during normal operations. When you eventually need them, git lfs pull --include="assets/audio/*" overrides the exclusion for that one command.
Fix 8: Set Up Git LFS in CI/CD Pipelines
CI/CD runners often do not have Git LFS installed, or they use shallow clones that skip LFS objects. This is a frequent source of smudge filter errors in automated builds.
GitHub Actions:
The default actions/checkout action does not fetch LFS objects. Enable it explicitly:
- uses: actions/checkout@v4
with:
lfs: trueIf you use a self-hosted runner, make sure git-lfs is installed on the runner machine.
GitLab CI:
Add LFS installation to your before_script:
before_script:
- apt-get update && apt-get install -y git-lfs
- git lfs install
- git lfs pullOr, if your GitLab runner supports it, set the GIT_LFS_SKIP_SMUDGE variable to skip LFS during clone and pull selectively:
variables:
GIT_LFS_SKIP_SMUDGE: "1"
build:
script:
- git lfs pull --include="assets/required/*"
- make buildJenkins:
In your Jenkinsfile, add an LFS pull step:
stage('Checkout') {
steps {
checkout scm
sh 'git lfs install'
sh 'git lfs pull'
}
}If your CI build fails with exit code 1 during checkout, see our guide on fixing GitHub Actions exit code failures for general troubleshooting steps.
Fix 9: Fix Corrupted LFS Pointer Files
Sometimes LFS pointer files get corrupted during merge conflicts or when someone commits the actual binary content without LFS installed. Git then tries to run the smudge filter on content that is not a valid pointer, causing the error.
Detect corrupted pointers:
git lfs fsckIf you see errors like “pointer file error” or “object missing,” the pointer files need to be repaired. First, check which files are affected:
git lfs ls-filesFor each corrupted file, reset it:
git checkout origin/main -- path/to/corrupted-file.binIf the file was committed directly (not as a pointer), you need to re-track it through LFS. Remove it from Git’s index, then add it back:
git rm --cached path/to/file.bin
git add path/to/file.bin
git commit -m "fix: re-add file through LFS"To migrate existing large files that were accidentally committed directly into the repository, use:
git lfs migrate import --include="*.bin" --everythingThis rewrites history so that all .bin files across all branches are stored through LFS. After migrating, you will need to force push all affected branches. Coordinate with your team before doing this, since it rewrites commit hashes (similar to how a rebase changes history — if you run into issues with that, our guide on fixing rebase conflicts covers the fundamentals).
Fix 10: Configure a Self-Hosted LFS Server
If you are using a self-hosted Git server or want to store LFS objects on your own infrastructure, you need to configure the LFS endpoint. The smudge filter will fail if it points to the wrong server.
Set the LFS URL for your repository:
git config lfs.url "https://lfs.yourcompany.com/repo"For S3-compatible storage, you can use a transfer agent like lfs-s3:
git config lfs.customtransfer.s3.path /usr/local/bin/lfs-s3
git config lfs.customtransfer.s3.args ""
git config lfs.standalonetransferagent s3Verify your LFS configuration:
git lfs envCheck the Endpoint line. If it shows (auth=none) and your server requires authentication, add credentials:
git config lfs.url "https://username:[email protected]/repo"Or better, use a credential helper so you are not storing tokens in Git config:
git config --global credential.https://lfs.yourcompany.com.helper storeIf your self-hosted server uses a TLS certificate that is not in the system trust store, you may need to specify the CA bundle:
git config http.https://lfs.yourcompany.com.sslCAInfo /path/to/ca-bundle.crtFix 11: Understand Smudge vs Clean Filters
Knowing how LFS filters work helps you diagnose unusual failures. Git LFS uses two filters:
- Clean filter (
git-lfs clean): Runs when yougit adda file. It uploads the large file content to the LFS server and replaces the file in Git’s index with a small pointer file. - Smudge filter (
git-lfs smudge): Runs when yougit checkouta file. It reads the pointer file, downloads the actual content from the LFS server, and replaces the pointer with the real file.
The smudge filter error means the download step failed. You can run the smudge filter manually to see the detailed error:
git lfs smudge < path/to/pointer-fileOr check what LFS would do without actually running the filter:
git lfs pointer --check --file path/to/fileThis tells you whether the file is a valid LFS pointer, the actual content, or something corrupted.
You can also debug filter operations by enabling verbose logging:
GIT_TRACE=1 GIT_LFS_LOG_FILE=lfs-debug.log git checkout -- path/to/fileThen inspect lfs-debug.log for detailed error messages. This is particularly helpful when the error message from Git itself is generic or truncated.
Fix 12: Reset and Re-fetch All LFS Objects
When nothing else works, a full reset of LFS objects often resolves stubborn issues. This is the nuclear option that re-downloads everything. It is useful when LFS objects in your local cache have become corrupted (for example, after a disk error or a power failure during a download) or when you suspect the local cache is out of sync with the remote:
# Clear the local LFS cache
rm -rf .git/lfs/objects
# Re-fetch all LFS objects for the current branch
git lfs fetch
# Replace pointer files with actual content
git lfs checkoutIf you need objects from all branches (not just the current one):
git lfs fetch --allIf the repository is in a broken state after a failed clone, it may be easier to start fresh. Clone with smudge filters disabled, then pull the LFS objects:
rm -rf repo
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/user/repo.git
cd repo
git lfs pullThis separates the Git clone from the LFS download, making it easier to diagnose which step is failing. If the clone succeeds but git lfs pull fails, the problem is with LFS server connectivity or credentials, not with Git itself. If you encounter errors during the clone step about the repository not being found, our guide on the “not a git repository” error covers common repository path issues.
Still Not Working?
LFS lock conflicts
If you are using LFS file locking and get smudge errors alongside lock-related messages, check the lock state:
git lfs locksUnlock files that are blocking your checkout:
git lfs unlock path/to/file.bin --forceProxy or firewall blocking LFS
Corporate proxies sometimes block LFS traffic because it uses different endpoints than regular Git operations. Configure Git to use your proxy:
git config --global http.proxy http://proxy.company.com:8080
git config --global https.proxy https://proxy.company.com:8080If only LFS is blocked, set the proxy for the LFS endpoint specifically:
git config http.https://lfs.github.com.proxy http://proxy.company.com:8080Stale Git index after switching branches
Sometimes the smudge error appears after switching between branches that have different .gitattributes configurations. One branch tracks *.bin with LFS, another does not. Switching between them can leave the Git index in an inconsistent state. Clear it and re-checkout:
git rm --cached -r .
git reset --hard HEAD
git lfs pullThis forces Git to re-read .gitattributes and apply the correct filters to all files. If the git reset step gives you merge conflict warnings, you may want to look at our guide on resolving merge conflicts.
Antivirus or security software interference
Some endpoint security tools intercept and scan large file downloads, causing the LFS transfer to time out or fail. If you suspect this, check your security software logs and add an exception for the git-lfs process.
Git version incompatibility
Older versions of Git may not support the LFS filter protocol correctly. Update Git to the latest version:
git --version
git lfs versionUse Git 2.30+ and Git LFS 3.0+ for the best compatibility. Older combinations can have subtle bugs in filter process handling that cause intermittent smudge failures. You can install the latest Git from git-scm.com and the latest LFS from git-lfs.com.
Verify your SSH setup
If LFS uses SSH for transfers and you recently changed your SSH configuration, verify your keys are loaded:
ssh-add -l
ssh -T [email protected]For detailed SSH troubleshooting, see our guide to fixing SSH publickey errors.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Git "cannot lock ref" – Unable to Create Lock File
How to fix the Git error 'cannot lock ref: Unable to create .git/refs/heads/branch-name.lock' caused by stale lock files, case conflicts, packed-refs corruption, and concurrent operations.
Fix: Git fatal: not a valid object name: 'main'
How to fix Git fatal not a valid object name error caused by empty repositories, wrong branch names, missing initial commits, and corrupted refs.
Fix: Git "Your local changes would be overwritten by merge"
How to fix Git error 'Your local changes to the following files would be overwritten by merge' using git stash, commit, checkout, and pull strategies.
Fix: fatal: remote origin already exists
How to fix the 'fatal: remote origin already exists' error in Git by updating the remote URL, removing and re-adding origin, managing multiple remotes, and handling forked repos.