This error occurs when you try to access, apply, drop, or pop a stash entry that doesn't exist. Common causes include referencing a stash index that has already been dropped, shell escaping issues with curly braces, or a corrupted stash reflog.
When Git manages stashes, it stores them as a stack using the reflog mechanism. Each stash is referenced by its position in this stack: `stash@{0}` is the most recent stash, `stash@{1}` is the one before it, and so on. When you see "stash@{n} is not a valid reference", Git is telling you that the stash entry you're trying to access doesn't exist. This error commonly occurs in several scenarios: 1. **The stash index doesn't exist**: You're trying to access a stash that was never created or has already been dropped. For example, if you only have 3 stashes (0, 1, 2), trying to access `stash@{5}` will fail. 2. **Shell escaping issues**: Shells like Bash, Zsh, and especially PowerShell may interpret the curly braces `{}` as special syntax. This can mangle the stash reference before Git receives it. 3. **Corrupted stash reflog**: After operations like `git filter-branch`, repository repairs, or interrupted Git operations, the stash reflog can become corrupted or inconsistent. 4. **Stash indices shifted**: When you drop or pop a stash, all subsequent stash indices shift down. A stash that was at `stash@{5}` might now be at `stash@{4}` after dropping `stash@{0}`.
First, check what stashes actually exist in your repository:
git stash listExample output:
stash@{0}: WIP on main: abc1234 Add new feature
stash@{1}: WIP on main: def5678 Fix bug
stash@{2}: WIP on develop: 9876fed Work in progressIn this example, only stash indices 0, 1, and 2 exist. Trying to access stash@{3} or higher would result in the "not a valid reference" error.
If the list is empty, you have no stashes at all. The stash you're looking for may have been dropped, popped, or never created.
Many shells interpret curly braces {} as special characters. Quoting the reference ensures Git receives it correctly.
For Bash/Zsh/Linux/Mac:
# Use single quotes
git stash apply 'stash@{0}'
# Or use double quotes
git stash drop "stash@{0}"
# Or escape the braces
git stash show stash@\{0\}For PowerShell (Windows):
# Use single quotes
git stash apply 'stash@{0}'
# Or use backticks to escape
git stash apply stash@`{0`}
# Or use the -- separator
git stash apply -- 'stash@{0}'For cmd.exe (Windows Command Prompt):
# Curly braces don't need escaping in cmd
git stash apply stash@{0}If quoting resolves the issue, consider adding a shell alias for convenience.
Some Git commands accept a simple numeric index instead of the full stash@{n} syntax:
# Apply stash by index (some versions support this)
git stash apply --index 0
# For dropping, you can use reflog delete
git reflog delete stash@{0}Alternative approach using the stash's commit SHA:
# Find the commit hash of the stash
git reflog show stash
# Output example:
# abc1234 stash@{0}: WIP on main: abc1234 Add feature
# def5678 stash@{1}: WIP on main: def5678 Fix bug
# Apply using the commit hash directly
git stash apply abc1234Using the commit hash bypasses the reference parsing entirely.
If your stash reflog is corrupted (often after git filter-branch or interrupted operations), you may need to repair or clear it.
Option 1: Clear all stashes (if data loss is acceptable):
git stash clearWarning: This permanently deletes ALL stashes. Only use if you don't need the stashed changes.
Option 2: Delete specific corrupted stash entries:
# Delete a specific stash entry from the reflog
# Work in reverse order (highest index first) to avoid shifting issues
git reflog delete stash@{2}
git reflog delete stash@{1}
git reflog delete stash@{0}Option 3: Remove the corrupted stash log file:
# Backup first
cp .git/logs/refs/stash .git/logs/refs/stash.backup
# Remove the log file
rm .git/logs/refs/stash
# Git stash should work again (but existing stashes will be lost)
git stash listOption 4: Also remove stash.lock if it exists:
rm -f .git/refs/stash.lock
rm -f .git/logs/refs/stash.lockIf you accidentally dropped a stash or it disappeared due to corruption, you may be able to recover it from the reflog.
Step 1: Find the lost stash commit:
# Show stash reflog history
git reflog show stash
# If that doesn't work, search the general reflog
git reflog | grep -i stash
# Or search for dangling commits
git fsck --unreachable | grep commitStep 2: Verify it's the right commit:
# Show what changes the commit contains
git show <commit_hash>Step 3: Re-add the commit to the stash:
# Add the commit back to the stash reference
git update-ref refs/stash <commit_hash>
# Verify it's restored
git stash listStep 4: Apply the recovered stash:
git stash applyNote: Stash commits have a specific structure with multiple parents. The recovery creates a simple reference, which works for git stash apply but some edge cases may behave differently.
If your repository is in a cloud-synced folder (Dropbox, OneDrive, Google Drive, iCloud), file conflicts can create duplicate or corrupted stash files.
Check for duplicate stash files:
# Look for unusual files in refs
ls -la .git/refs/
# Check for files like "stash (1)" or "stash (2)"
find .git -name "stash*" -type fRemove duplicate files:
# If you find files like .git/refs/stash (1)
rm ".git/refs/stash (1)"
rm ".git/logs/refs/stash (1)"Best practice: Avoid storing Git repositories in cloud-synced folders. The constant syncing can cause file locks and conflicts. Instead:
1. Keep repositories in a non-synced location
2. Use Git remotes (GitHub, GitLab, etc.) for backup and sync
3. If you must use cloud storage, consider pausing sync during Git operations
After applying fixes, verify that stash operations work correctly:
# List current stashes
git stash list
# Create a test stash
echo "test" > test-stash-file.txt
git stash push -m "Test stash"
# Verify the test stash was created
git stash list
# Apply and drop the test stash
git stash pop
# Clean up
rm test-stash-file.txtIf issues persist:
1. Check if the repository itself is corrupted:
git fsck --full2. Consider cloning a fresh copy if the repo is available remotely:
git clone <remote-url> fresh-clone
cd fresh-clone3. If this is a shared or CI environment, ensure proper Git configuration and permissions.
### Understanding Git Stash Internals
Git stashes are stored using the reflog mechanism, which maintains a history of reference changes. The actual stash data is stored as commits with a special structure:
- The stash commit has 2 or 3 parents:
1. The HEAD commit at the time of stashing
2. The index (staged changes) commit
3. (Optional) Untracked files commit (if --include-untracked was used)
View the internal structure:
git log --oneline --graph stash@{0}### Stash Index Behavior
When you drop or pop a stash, all subsequent indices shift down:
Before: After git stash drop stash@{1}:
stash@{0}: Feature A stash@{0}: Feature A
stash@{1}: Feature B stash@{1}: Feature C (was @{2})
stash@{2}: Feature C stash@{2}: Feature D (was @{3})
stash@{3}: Feature DThis is why scripts that reference specific stash indices can fail unexpectedly if another process or user modifies the stash in between.
### Automation and Scripting Considerations
When scripting with git stash, always:
1. Quote references properly for the target shell
2. Check stash existence before operations:
if git rev-parse --verify --quiet stash@{0} > /dev/null 2>&1; then
git stash pop
fi3. Use commit hashes instead of indices for reliability:
# Get the hash of stash@{0}
STASH_HASH=$(git rev-parse stash@{0})
# Use the hash for subsequent operations
git stash apply $STASH_HASH4. Handle the case where no stashes exist:
STASH_COUNT=$(git stash list | wc -l)
if [ "$STASH_COUNT" -gt 0 ]; then
git stash pop
fi### Common Pitfalls with git filter-branch
Running git filter-branch can invalidate or corrupt stashes because it rewrites repository history. The stash commits may reference commits that no longer exist.
Prevention: Before running git filter-branch:
# Save stash contents to patch files
git stash list | while read -r line; do
idx=$(echo "$line" | grep -oP 'stash@\{\K\d+')
git stash show -p "stash@{$idx}" > "stash-$idx.patch"
done
# Clear stashes before filter-branch
git stash clear
# Run filter-branch
git filter-branch ...
# Re-apply stashes from patches if needed
git apply stash-0.patch
git stash push -m "Restored stash 0"### GUI Tools and IDE Integration
Many Git GUIs (GitKraken, SourceTree, VS Code Git extension, etc.) handle stash references internally and avoid shell escaping issues. If you frequently encounter this error in the terminal:
1. Consider using a Git GUI for stash operations
2. Or configure a Git alias that handles quoting:
git config --global alias.stashget '!f() { git stash apply "stash@{$1}"; }; f'
git stashget 0 # Now works without quotingwarning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server