hashicorp/terraform · error
cannot hash package at %s
Error message
cannot hash package at %s
What it means
PackageHashV1 (and the public Hash/MatchesHash) can only hash a provider package whose contents are readable on the local filesystem, i.e. a PackageLocalDir or PackageLocalArchive. The type switch's default branch returns this error for any other PackageLocation because there is nothing local to read. This contract is documented on Hash(): non-local locations always error. It is an invariant violation, not a runtime/network condition.
Source
Thrown at internal/getproviders/hash.go:308
// The dirhash.HashDir result is already in our expected h1:...
// format, so we can just convert directly to Hash.
s, err := dirhash.HashDir(packageDir, "", dirhash.Hash1)
return Hash(s), err
case PackageLocalArchive:
archivePath, err := filepath.EvalSymlinks(string(loc))
if err != nil {
return "", err
}
// The dirhash.HashDir result is already in our expected h1:...
// format, so we can just convert directly to Hash.
s, err := dirhash.HashZip(archivePath, dirhash.Hash1)
return Hash(s), err
default:
return "", fmt.Errorf("cannot hash package at %s", loc.String())
}
}
// Hash computes a hash of the contents of the package at the location
// associated with the reciever, using whichever hash algorithm is the current
// default.
//
// This method will change to use new hash versions as they are introduced
// in future. If you need a specific hash version, call the method for that
// version directly instead, such as HashV1.
//
// Hash can be used only with the two local package location types
// PackageLocalDir and PackageLocalArchive, because it needs to access the
// contents of the indicated package in order to compute the hash. If given
// a non-local location this function will always return an error.
func (m PackageMeta) Hash() (providerreqs.Hash, error) {
return PackageHash(m.Location)
}View on GitHub (pinned to c9def3e214)
Solutions
- Download and materialize the package first so its location becomes PackageLocalArchive or PackageLocalDir before calling Hash().
- If you already have a local directory, wrap it as PackageLocalDir(path); if you have a zip file, wrap it as PackageLocalArchive(path).
- Narrow on the concrete location type with a type switch and only call Hash() for the two hashable cases.
Example fix
// before meta, _ := src.PackageMeta(ctx, p, v, plat) want, _ := meta.Hash() // errors: meta.Location is PackageHTTPURL // after // install/download first; installer.rewritePackageLocalArchive yields a local archive archivePath, _ := installer.DownloadAndUnpack(ctx, meta, cacheDir) local := getproviders.PackageLocalArchive(archivePath) want, err := getproviders.PackageHash(local)
Defensive patterns
Strategy: type-guard
Validate before calling
// Only local archive/dir locations are hashable.
switch loc.(type) {
case getproviders.PackageLocalArchive, getproviders.PackageLocalDir:
// safe to hash
default:
return fmt.Errorf("location %T is not locally hashable; download first", loc)
} Type guard
func isHashablePackageLocation(loc getproviders.PackageLocation) bool {
switch loc.(type) {
case getproviders.PackageLocalArchive, getproviders.PackageLocalDir:
return true
}
return false
} Prevention
- Always run the installer's download step before computing a hash.
- Keep a type switch over PackageLocation wherever you handle locations.
- Treat PackageHTTPURL as not-yet-materialized: never hash it directly.
When it happens
Trigger: Calling PackageHash(loc) / PackageHashV1(loc) / PackageMeta.Hash() with a location that is a PackageHTTPURL (download URL not yet fetched) or a PackageLocalURL (unpacked-but-not-materialized). Commonly hit when hashing a PackageMeta returned by Source.PackageMeta() before the installer downloads and rewrites the location to a local archive/dir.
Common situations: Test helpers that build PackageMeta with an HTTP location and then call MatchesHash; refactors that moved hashing before the download/install step; code that iterates Source results and tries to verify hashes up front.
Related errors
- expected on 1 response value, got: %d
- failed to read state: %w
- unsupported action trigger type: %T
- resource %s has an unsupported mode %s
- unknown value type in TypeMap %T
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/691eb6b7d8b3a99e.
Report an issue: GitHub.