What's Actually Happening
Go module dependencies have version conflicts. Different modules require incompatible versions of the same dependency.
The Error You'll See
```bash $ go build
go: github.com/example/pkg@v1.2.0 requires github.com/other/lib@v1.0.0: missing go.sum entry ```
Version mismatch:
go: inconsistent vendoring:
github.com/dep/lib: version varies (v1.0.0 vs v1.1.0)Minimal version selection error:
go: github.com/project/pkg imports
github.com/dep/lib: ambiguous import: found github.com/dep/lib in multiple modulesUpdate conflict:
```bash $ go get github.com/example/pkg@latest
go: github.com/example/pkg@v2.0.0 requires github.com/dep/lib@v2.0.0: already have github.com/dep/lib@v1.0.0 ```
Why This Happens
- 1.Version requirements conflict - Dependencies require different versions
- 2.Major version mismatch - Different major versions imported
- 3.Indirect dependency conflict - Transitive dependency version issue
- 4.Missing go.sum entry - Module not in go.sum
- 5.Vendoring inconsistency - Vendor directory out of sync
- 6.Replace directive missing - Local replacement not configured
Step 1: Analyze Dependency Graph
```bash # View dependency graph: go mod graph
# Check specific package: go mod graph | grep github.com/dep/lib
# View why dependency is needed: go mod why github.com/dep/lib
# View all dependencies: go list -m all
# Check for updates: go list -u -m all
# View dependency versions: go list -m -versions github.com/dep/lib
# View module info: go mod download -json github.com/dep/lib
# Check import chain: go mod why -m github.com/dep/lib ```
Step 2: Clean Module Cache
```bash # Clear module cache: go clean -modcache
# Remove go.sum: rm go.sum
# Re-download: go mod download
# Tidy dependencies: go mod tidy
# Rebuild: go build ./...
# If using vendor: rm -rf vendor go mod vendor ```
Step 3: Update Dependencies
```bash # Update all dependencies: go get -u ./...
# Update specific package: go get github.com/dep/lib@v1.2.0
# Update to latest: go get github.com/dep/lib@latest
# Update to specific commit: go get github.com/dep/lib@abc123
# Update to specific branch: go get github.com/dep/lib@main
# Update indirect dependencies: go get -u=patch ./...
# Tidy after update: go mod tidy
# Verify: go mod verify ```
Step 4: Use Replace Directive
```go // In go.mod:
module myproject
go 1.21
require ( github.com/example/pkg v1.0.0 github.com/other/lib v2.0.0 )
// Replace with different version: replace github.com/dep/lib => github.com/dep/lib v1.2.0
// Replace with local module: replace github.com/dep/lib => ../local-lib
// Replace with fork: replace github.com/original/lib => github.com/fork/lib v1.0.0
// Multiple replacements: replace ( github.com/dep/lib => github.com/dep/lib v1.2.0 github.com/other/pkg => ../local/pkg ) ```
# After adding replace, update:
go mod tidyStep 5: Handle Major Version Changes
```go // Go uses major version in import path for v2+:
// v1.x.x: import "github.com/dep/lib"
// v2.x.x: import "github.com/dep/lib/v2"
// v3.x.x: import "github.com/dep/lib/v3"
// In go.mod: require ( github.com/dep/lib v1.2.0 // v1 github.com/dep/lib/v2 v2.3.0 // v2 (different module) )
// If both needed, they're treated as different modules // This avoids most version conflicts ```
```bash # Update to v2+: go get github.com/dep/lib/v2@latest
# Update imports: // Change all imports from "github.com/dep/lib" to "github.com/dep/lib/v2" ```
Step 6: Fix Indirect Dependency Conflicts
```bash # Check indirect dependencies: grep "// indirect" go.mod
# Explicitly set version: go mod edit -require=github.com/dep/lib@v1.2.0
# Or add to go.mod: require github.com/dep/lib v1.2.0
// Then: go mod tidy
# If conflict with indirect: # 1. Update main dependencies to compatible versions # 2. Use replace directive # 3. Check if dependency updates available
# Example: Find minimum compatible version: go mod graph | grep github.com/dep/lib | sort -V | head -5 ```
Step 7: Fix Vendor Issues
```bash # Sync vendor with go.mod: go mod vendor
# Clean vendor and rebuild: rm -rf vendor go mod vendor
# Build with vendor: go build -mod=vendor ./...
# Test with vendor: go test -mod=vendor ./...
# Verify vendor matches: diff -r vendor/github.com/dep/lib <(go mod download -json github.com/dep/lib | jq -r .Dir)
# Update vendor after go.mod change: go mod tidy go mod vendor ```
Step 8: Debug Version Selection
```bash # Enable module debug: GOPROXY=https://proxy.golang.org,direct go mod download
# Check which version selected: go list -m github.com/dep/lib
# Check all versions: go list -m -versions github.com/dep/lib
# Check why version was selected: go mod download -json github.com/dep/lib | jq '.Version, .Time, .GoMod'
# Use verbose output: go get -v -x github.com/dep/lib@v1.2.0
# Check module requirements: go mod edit -json | jq '.Require'
# Check replacements: go mod edit -json | jq '.Replace'
# Minimal version selection explanation: # Go selects the minimum version that satisfies all requirements ```
Step 9: Fix Specific Conflict Patterns
```bash # Pattern 1: Ambiguous import # Error: found package in multiple modules
# Fix: Use explicit version in import or replace replace github.com/dep/lib => github.com/dep/lib v1.2.0
# Pattern 2: Pseudo-version conflict # Error: invalid pseudo-version
# Fix: Use explicit version go get github.com/dep/lib@v1.2.0
# Pattern 3: Incompatible Go version # Error: go directive in go.mod too old
# Fix: Update go directive go mod edit -go=1.21
# Pattern 4: Removed dependency still referenced # Fix: Clean and rebuild go mod tidy go clean -cache
# Pattern 5: Cyclic dependency # Fix: Refactor to remove cycle # Or use interface to break dependency ```
Step 10: Go Module Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-go-modules.sh #!/bin/bash
PKG=${1:-""}
echo "=== Go Version ===" go version
echo "" echo "=== go.mod Summary ===" head -20 go.mod
echo "" echo "=== Direct Dependencies ===" grep -v "// indirect" go.mod | grep -E "^\s+github.com"
echo "" echo "=== Indirect Dependencies ===" grep "// indirect" go.mod
echo "" echo "=== Outdated Dependencies ===" go list -u -m all 2>/dev/null | grep '[' | head -10
if [ -n "$PKG" ]; then echo "" echo "=== Package: $PKG ===" echo "Why needed:" go mod why $PKG echo "" echo "Available versions:" go list -m -versions $PKG 2>/dev/null | tr ' ' '\n' | head -10 echo "" echo "Current version:" go list -m $PKG fi
echo "" echo "=== go.sum Status ===" wc -l go.sum echo "Unique modules:" cut -d' ' -f1 go.sum | sort -u | wc -l
echo "" echo "=== Vendor Status ===" if [ -d "vendor" ]; then echo "Vendor directory exists" ls vendor | wc -l else echo "No vendor directory" fi
echo "" echo "=== Build Test ===" go build ./... 2>&1 | head -5 || echo "Build failed"
echo "" echo "=== Recommendations ===" echo "1. Run 'go mod tidy' to clean unused dependencies" echo "2. Run 'go get -u' to update dependencies" echo "3. Check 'go mod why <pkg>' for dependency chain" echo "4. Use 'replace' directive for version conflicts" EOF
chmod +x /usr/local/bin/check-go-modules.sh
# Usage: /usr/local/bin/check-go-modules.sh github.com/dep/lib
# Quick check: alias go-deps='go list -m all | head -20' ```
Go Module Checklist
| Check | Command | Expected |
|---|---|---|
| go.mod valid | go mod verify | Clean |
| No conflicts | go mod tidy | No errors |
| Build succeeds | go build ./... | Success |
| Versions match | go list -m all | Consistent |
| Vendor synced | go mod vendor | Updated |
| Dependencies clean | go mod why | All used |
Verify the Fix
```bash # After fixing module conflict
# 1. Clean and rebuild go mod tidy go build ./... // Build succeeds
# 2. Check dependency tree go mod graph | grep conflict-pkg // Single version listed
# 3. Verify go.mod cat go.mod // Replace directives if needed
# 4. Run tests go test ./... // All tests pass
# 5. Check for updates go list -u -m all // No security issues
# 6. Commit changes git add go.mod go.sum git commit -m "fix: resolve module version conflicts" ```
Related Issues
- [Fix Go Module Not Found](/articles/fix-go-module-not-found)
- [Fix Go Build Failed](/articles/fix-go-build-failed)
- [Fix Go Test Failed](/articles/fix-go-test-failed)