Overview
Git LFS replaces large files in Git with small pointer files and downloads real content during checkout via the smudge filter. When that download fails, you’ll see errors like:
- smudge filter lfs failed
- Error downloading object: <oid>
- batch response: 403/404/429 or Authentication required
Common causes:
- Missing or expired credentials
- Rate limit or storage/bandwidth quota exceeded
- Network/proxy/TLS issues
- Corrupted or partial LFS objects locally
- LFS not installed/activated, or pointer mismatch after history rewrite
This guide shows quick fixes, a minimal working example, step-by-step troubleshooting, pitfalls, performance tips, and a tiny FAQ.
Quickstart (most cases)
If a clone or checkout fails with a smudge error, avoid downloading during checkout, then fetch and materialize LFS files explicitly.
- Ensure Git LFS is installed and active
git lfs version
# If needed, (re)install filters in this repo
git lfs install --force
- Temporarily skip smudge, then pull
# In the affected repo
git config --local filter.lfs.smudge "git-lfs smudge --skip -- %f"
git config --local filter.lfs.required false
git pull --rebase --autostash
- Fetch LFS objects and restore working files
# Fetch LFS content for current refs
git lfs fetch --all --prune
# Replace pointer files with real content
git lfs checkout
- Re-enable normal LFS behavior
git lfs install --force # restores smudge/clean filters
If authentication prompts appear, complete them. If you still get errors, follow the troubleshooting steps below.
Minimal working example
This sets up a local repo using LFS to show correct configuration and the skip-smudge workflow.
set -e
# Create a fresh repo
rm -rf demo-lfs
mkdir demo-lfs && cd demo-lfs
git init
echo "*.bin filter=lfs diff=lfs merge=lfs -text" > .gitattributes
git lfs install --force
git add .gitattributes
git commit -m "Init LFS tracking for *.bin"
# Create a large binary and commit via LFS
head -c 1048576 </dev/urandom > sample.bin
git add sample.bin
git commit -m "Add sample.bin via LFS"
# Demonstrate skipping smudge locally (e.g., in CI or when cloning)
# Simulate disabling smudge, then re-enabling and materializing content
git config --local filter.lfs.smudge "git-lfs smudge --skip -- %f"
git config --local filter.lfs.required false
# Remove the file from working tree and re-checkout via LFS
rm -f sample.bin
git checkout -- sample.bin # pointer is checked out without downloading
# Now fetch (noop here since local) and materialize via checkout
git lfs fetch --all --prune
git lfs checkout # restores sample.bin from local LFS store
# Restore normal behavior
git lfs install --force
echo "OK"
Notes:
- In real clones, fetch pulls from the remote LFS server. In this local demo, the object already exists in the repo’s LFS store.
Step-by-step troubleshooting
- Verify LFS is installed and filters are active
- Commands:
git lfs version
git lfs env | sed -n '1,80p'
- Look for filter.lfs.* entries and a valid LFS endpoint for your remote.
- Re-authenticate
- Run a command that triggers auth and follow prompts:
git lfs fetch --all
- If using HTTPS, ensure your credential helper is set:
git config credential.helper
- If using SSH, confirm your remote uses SSH and that SSH keys/agent are working.
- Bypass smudge to get the Git history first
- For an existing repo that can’t checkout:
git config --local filter.lfs.smudge "git-lfs smudge --skip -- %f"
git config --local filter.lfs.required false
git pull --rebase
- Then fetch and materialize:
git lfs fetch --all --prune
git lfs checkout
- Clean corrupt or partial local LFS objects
git lfs prune # removes old/incomplete LFS objects safely
Then retry fetch/checkout.
- Limit concurrency and tune timeouts for flaky networks
git config --global lfs.concurrenttransfers 3
# Optional: increase retries
git config --global lfs.transfer.maxretries 10
- Check for pointer mismatches after history changes
- If files were added without LFS or history was rewritten, pointers may be invalid.
- Validate LFS state:
git lfs fsck
- If necessary (and with care), migrate history to LFS:
git lfs migrate import --include="*.bin" --everything
Warning: migration rewrites history; coordinate with your team.
- Quota or policy blocks
- Errors like 403/429 often signal bandwidth/storage limits or access policies. Resolve quotas or request access, then fetch again.
Common errors and quick fixes
| Error snippet | Likely cause | Quick fix |
|---|---|---|
| Authentication required | Expired/missing credentials | Re-auth; run git lfs fetch to prompt; fix credential helper |
| 403 Forbidden | Access or quota limit | Confirm access; resolve storage/bandwidth limits |
| 404 Not Found | Wrong LFS endpoint or object missing | Check remote URL; verify file was pushed via LFS |
| 429 Too Many Requests | Rate limit | Retry later; reduce lfs.concurrenttransfers |
| smudge filter lfs failed | Download blocked by network, proxy, TLS | Configure proxy/TLS; retry with skip-smudge then fetch |
Pitfalls
- Forgetting to run git lfs install after fresh environment setup.
- Mixing tracked patterns so large files bypass LFS; fix .gitattributes early.
- Forcing history migrations on shared branches without coordination.
- Manually deleting .git/lfs directories instead of using git lfs prune.
- Assuming shallow clones fully avoid LFS downloads; LFS still needs objects per checkout.
Performance notes
- Use GIT_LFS_SKIP_SMUDGE=1 or git lfs install --skip-smudge to speed up clones; fetch only what you need.
- Limit parallel transfers on slow links:
git config --global lfs.concurrenttransfers 3
- Fetch recent objects only to reduce bandwidth:
git config --global lfs.fetchrecentalways true
git config --global lfs.fetchrecentrefsdays 7
- Periodically prune to free disk space:
git lfs prune
FAQ
Why does clone fail with a smudge error?
- The checkout phase tries to download LFS files before credentials/network are ready. Skip smudge, complete auth, then fetch/checkout.
How do I fix this in CI?
- Run git lfs install --skip-smudge before clone/checkout, then git lfs fetch and git lfs checkout only the needed paths.
Can I avoid downloading all LFS files?
- Yes. Skip smudge, then use include/exclude:
git lfs fetch --include="path/**" --exclude=""
git lfs checkout path/
- I still see 404 for an object. What next?
- The object may never have been pushed to the LFS server. Verify that the contributor pushed with Git LFS enabled, then try fetch/checkout again.