The 'is not a valid tag name' error occurs when Git rejects a tag name that violates its reference naming rules. Git tags must follow strict conventions that prohibit certain characters and patterns. Rename your tag using only allowed characters to resolve this error.
This error indicates that Git's reference format validator has rejected your proposed tag name. Git uses a unified naming system for all references (branches, tags, remotes), and tags must conform to rules defined in `git-check-ref-format`. When you run `git tag <name>`, Git first validates that the name follows its reference naming rules before creating the tag. If the name contains forbidden characters or patterns, Git immediately rejects it with the "is not a valid tag name" fatal error. The validation exists because Git references are stored as files in the `.git/refs/` directory, and invalid characters could cause filesystem issues, security problems, or conflicts with Git's internal parsing. Additionally, tags need to work across different operating systems with varying filesystem constraints.
First, use Git's built-in validation tool to check if a tag name is valid:
# Check if a tag name is valid
git check-ref-format "refs/tags/your-tag-name" && echo "Valid" || echo "Invalid"
# Alternative: check with the tags prefix
git check-ref-format --allow-onelevel "your-tag-name" && echo "Valid" || echo "Invalid"If the tag is invalid, review it for these forbidden patterns:
- Spaces or control characters
- Special characters: ~ ^ : ? * [ \ @
- Double dots: ..
- Leading/trailing slashes or dots
- The sequence @{
Replace invalid characters with allowed alternatives. Common substitutions:
# Instead of spaces, use hyphens or underscores
git tag "v1.0-beta-1" # Not: "v1.0 beta 1"
# Instead of special characters, use descriptive text
git tag "v2.0-feature-x" # Not: "v2.0[feature]"
git tag "v1.0-rc1" # Not: "v1.0~rc1"
# Use single dots, not double
git tag "v1.0.1" # Not: "v1..1"
# Valid characters for Git tags:
# - Alphanumeric: a-z, A-Z, 0-9
# - Hyphens: -
# - Underscores: _
# - Single dots: .
# - Forward slashes: / (not at start/end)Some characters are interpreted by your shell before reaching Git. Quote your tag names to prevent this:
# Brackets are interpreted by shells like zsh
git tag "[1.0]" # zsh: no matches found: [1.0]
# Even with quotes, these characters are still invalid in Git
# The error changes from shell error to Git error
git tag 'v1.0[beta]' # fatal: 'v1.0[beta]' is not a valid tag name
# Solution: use valid characters instead
git tag "v1.0-beta"In zsh, you might see "no matches found" before Git even runs. This is a shell issue, but the underlying problem is using invalid characters.
Sometimes tag names contain invisible characters like newlines or carriage returns, especially when copied from elsewhere:
# Check for hidden characters using cat with special flags
echo "v1.0.0" | cat -A
# Should show: v1.0.0$
# If you see ^M or other symbols, there are hidden characters
# Check using hexdump
echo "v1.0.0" | hexdump -C
# Look for bytes other than expected ASCII letters/numbers
# In scripts, trim whitespace from variables
TAG_NAME=$(echo "$TAG_NAME" | tr -d '[:space:]')
git tag "$TAG_NAME"
# Or use parameter expansion in bash
TAG_NAME="${TAG_NAME//[$'\t\r\n']}"
git tag "$TAG_NAME"The safest approach is to use semantic versioning format, which is universally valid:
# Standard semantic versioning (always valid)
git tag "v1.0.0"
git tag "v2.1.3"
git tag "1.0.0" # v prefix is optional
# Pre-release versions (use hyphens, not tildes)
git tag "v1.0.0-alpha.1"
git tag "v1.0.0-beta.2"
git tag "v1.0.0-rc.1"
# Build metadata (use plus sign, which is valid)
git tag "v1.0.0+build.123"
git tag "v1.0.0-beta.1+sha.abc123"This format is recognized by most tools and CI/CD systems.
Git allows hierarchical tag names with slashes, but they have specific rules:
# Valid hierarchical tags
git tag "release/v1.0.0"
git tag "feature/awesome-feature"
# Invalid patterns
git tag "/v1.0.0" # Cannot start with /
git tag "v1.0.0/" # Cannot end with /
git tag "release//v1.0.0" # Cannot have consecutive slashes
git tag ".hidden/tag" # Components cannot start with .
git tag "release/v1.lock" # Components cannot end with .lock
# Fix by removing leading/trailing slashes
git tag "release/v1.0.0" # CorrectNote: Hierarchical tags create actual directory structures in .git/refs/tags/.
Use Git's normalize feature to help fix some issues automatically:
# Normalize a tag name (fixes consecutive slashes)
git check-ref-format --normalize "refs/tags/release//v1.0"
# Output: refs/tags/release/v1.0
# Create a shell function to validate before tagging
validate_tag() {
if git check-ref-format "refs/tags/$1" 2>/dev/null; then
echo "Valid tag name: $1"
return 0
else
echo "Invalid tag name: $1"
return 1
fi
}
# Use it before creating tags
validate_tag "v1.0.0" && git tag "v1.0.0"In automated pipelines, sanitize dynamic tag names before using them:
# Bash function to sanitize tag names
sanitize_tag() {
echo "$1" | \
tr '[:upper:]' '[:lower:]' | \ # Optional: lowercase
sed 's/[^a-zA-Z0-9._-]/-/g' | \ # Replace invalid chars
sed 's/--*/-/g' | \ # Remove consecutive hyphens
sed 's/^-//' | \ # Remove leading hyphen
sed 's/-$//' # Remove trailing hyphen
}
# Usage
RAW_TAG="v1.0 [beta]"
CLEAN_TAG=$(sanitize_tag "$RAW_TAG")
git tag "$CLEAN_TAG" # Creates: v1.0-betaFor GitHub Actions:
- name: Create sanitized tag
run: |
TAG_NAME=${{ github.event.inputs.tag }}
SAFE_TAG=$(echo "$TAG_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g')
git tag "$SAFE_TAG"
git push origin "$SAFE_TAG"### Complete List of Git Reference Name Rules
Git's git-check-ref-format defines these rules for all references (including tags):
1. No control characters - ASCII values below 040 (space) or 177 (DEL)
2. No special characters - space, ~, ^, :, ?, *, [, \
3. No double dots - .. sequence is forbidden anywhere
4. No at-brace - @{ sequence is forbidden
5. No single @ - Cannot be just the character @
6. No slash at boundaries - Cannot start or end with /
7. No consecutive slashes - // is not allowed
8. No component starting with dot - ./ or foo/.bar are invalid
9. No trailing dot - Cannot end with .
10. No .lock suffix - Components cannot end with .lock
### Why These Rules Exist
- Filesystem safety: Tags become files/directories in .git/refs/tags/
- Cross-platform: Rules ensure compatibility between Linux, macOS, and Windows
- Git syntax: Characters like ~, ^, and @ have special meaning in Git (e.g., HEAD~1, main^2, @{yesterday})
- URL safety: Tags may appear in URLs for remote operations
### Checking Multiple Tags at Once
# Validate multiple tag names from a file
while read tag; do
if git check-ref-format "refs/tags/$tag" 2>/dev/null; then
echo "VALID: $tag"
else
echo "INVALID: $tag"
fi
done < tags.txt### Platform-Specific Considerations
Windows has additional restrictions on filenames (e.g., CON, PRN, NUL). While Git may accept these as tag names on Linux, they can cause issues when cloning on Windows.
macOS uses a case-insensitive filesystem by default, so v1.0 and V1.0 would conflict even though Git considers them different.
### Common Tool Compatibility
| Tool | Tag Format | Example |
|------|------------|---------|
| npm/yarn | Semantic versioning | v1.2.3 |
| Go modules | Semantic with v prefix | v1.2.3 |
| Docker | Similar to Git | 1.2.3, latest |
| Helm | Semantic versioning | 1.2.3 |
Stick to alphanumeric characters, hyphens, dots, and underscores for maximum compatibility across all tools.
warning: 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