The Go compiler failed because two different packages, both imported by your code, provided the same identifier (a function, type, or variable) with the same name.

Common Causes and Fixes

  1. Direct Dependency Conflict:

    • Diagnosis: Run go list -m all and look for duplicate module versions. Then, run go mod graph to trace the import path of the conflicting identifier. You’re looking for a scenario where moduleA imports github.com/example/common v1.0.0 and moduleB imports github.com/example/common v1.1.0, and your code imports both moduleA and moduleB. The go mod graph output will show which top-level modules depend on which versions of the conflicting dependency.
    • Fix: Use go get -u github.com/example/common@latest or go get github.com/example/common@vX.Y.Z to force a specific version of the conflicting dependency. Then, run go mod tidy to clean up.
    • Why it works: Go’s module system resolves dependencies by choosing the highest version number that satisfies all requirements. If two different paths lead to different versions of the same module, Go will pick one. If that chosen version doesn’t have the identifier, or if the identifier changed between versions, you get an ambiguity. Forcing a specific version ensures all paths resolve to a consistent state.
  2. Indirect Dependency Conflict:

    • Diagnosis: The conflict might arise from dependencies of your dependencies. go mod graph is crucial here. Trace the import paths. You’ll see your_module -> dependency_A -> github.com/example/common v1.0.0, and your_module -> dependency_B -> github.com/example/common v1.1.0.
    • Fix: You can’t directly go get an indirect dependency. The solution is to update the direct dependencies (dependency_A or dependency_B) that are pulling in the conflicting indirect module. Try go get -u github.com/dependency_A@latest and go get -u github.com/dependency_B@latest. After updating, run go mod tidy. If that doesn’t work, you might need to manually edit your go.mod file to pin a specific version of the problematic indirect module, but this is generally discouraged as it can lead to unexpected behavior.
    • Why it works: By updating the direct dependencies, you’re hoping they have newer versions that no longer depend on the older, conflicting version of the indirect module, or that they’ve resolved their own dependency conflicts internally.
  3. Vendoring Issues:

    • Diagnosis: If you’re using go mod vendor, check the vendor/modules.txt file. It lists the exact versions of all dependencies. Compare this to your go.mod file and the output of go mod graph. Ensure the versions in vendor/modules.txt accurately reflect the resolved versions from go.mod and that there aren’t duplicate entries for the same module at different versions.
    • Fix: Delete the vendor directory and run go mod vendor again. This will regenerate the vendor directory based on your current go.mod and go.sum files, resolving any inconsistencies.
    • Why it works: The vendor directory is a snapshot. If it gets out of sync with your module definitions, it can lead to the compiler seeing different versions of packages than what go.mod indicates. Re-vending ensures consistency.
  4. Local Path Overrides:

    • Diagnosis: Check your go.mod file for replace directives. For example, replace github.com/example/common => ../local/path/to/common. If you have multiple replace directives pointing to different versions or locations of the same underlying package, or if one replace directive points to a version that conflicts with a non-replaced dependency, you’ll see this error.
    • Fix: Remove or correct the conflicting replace directive. Ensure that any local development paths you’re using don’t inadvertently introduce different versions of the same module.
    • Why it works: replace directives tell the Go toolchain to use a different module path or version than what’s declared in go.mod or fetched from a repository. This is powerful for local development but can easily cause conflicts if not managed carefully.
  5. Package Name Collisions (Less Common with Modules):

    • Diagnosis: This is rare with Go modules but could happen if you have two different packages with the same base name (e.g., github.com/userA/util and github.com/userB/util) and both export an identifier with the exact same name (e.g., const MaxInt). The error message will usually point to the specific identifier.
    • Fix: The ideal fix is for one of the upstream packages to rename their exported identifier. If you control one of the packages, rename the conflicting identifier. If you don’t, you might need to use a replace directive to alias one of the packages to a different path locally, and then adjust your imports. For example, replace github.com/userA/util => github.com/userA/util v1.0.0-local-alias and then import util_alias "github.com/userA/util".
    • Why it works: By aliasing one of the packages, you give it a distinct import path in your project, allowing the Go compiler to differentiate between the two identically named identifiers.
  6. Go Version Incompatibility:

    • Diagnosis: Ensure all your dependencies are compatible with the Go version specified in your go.mod file (e.g., go 1.20). Sometimes, older packages might not be aware of newer module resolution rules or might have been written for older Go versions where import conflicts were handled differently.
    • Fix: Update your go.mod to the latest stable Go version and run go get -u on all your direct dependencies. Then, run go mod tidy.
    • Why it works: Newer Go versions often have improved module resolution and stricter error checking, which can surface or help resolve underlying dependency issues.

The next error you’ll likely encounter is a "package not found" error if you’ve accidentally removed a necessary dependency while trying to resolve the ambiguity.

Want structured learning?

Take the full Golang course →