{"record":{"id":"691eb6b7d8b3a99e","repo":"hashicorp/terraform","slug":"cannot-hash-package-at-s","errorCode":null,"errorMessage":"cannot hash package at %s","messagePattern":"cannot hash package at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/hash.go","lineNumber":308,"sourceCode":"\n\t\t// The dirhash.HashDir result is already in our expected h1:...\n\t\t// format, so we can just convert directly to Hash.\n\t\ts, err := dirhash.HashDir(packageDir, \"\", dirhash.Hash1)\n\t\treturn Hash(s), err\n\n\tcase PackageLocalArchive:\n\t\tarchivePath, err := filepath.EvalSymlinks(string(loc))\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\t// The dirhash.HashDir result is already in our expected h1:...\n\t\t// format, so we can just convert directly to Hash.\n\t\ts, err := dirhash.HashZip(archivePath, dirhash.Hash1)\n\t\treturn Hash(s), err\n\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"cannot hash package at %s\", loc.String())\n\t}\n}\n\n// Hash computes a hash of the contents of the package at the location\n// associated with the reciever, using whichever hash algorithm is the current\n// default.\n//\n// This method will change to use new hash versions as they are introduced\n// in future. If you need a specific hash version, call the method for that\n// version directly instead, such as HashV1.\n//\n// Hash can be used only with the two local package location types\n// PackageLocalDir and PackageLocalArchive, because it needs to access the\n// contents of the indicated package in order to compute the hash. If given\n// a non-local location this function will always return an error.\nfunc (m PackageMeta) Hash() (providerreqs.Hash, error) {\n\treturn PackageHash(m.Location)\n}","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/getproviders/hash.go#L290-L326","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmeta, _ := src.PackageMeta(ctx, p, v, plat)\nwant, _ := meta.Hash() // errors: meta.Location is PackageHTTPURL\n\n// after\n// install/download first; installer.rewritePackageLocalArchive yields a local archive\narchivePath, _ := installer.DownloadAndUnpack(ctx, meta, cacheDir)\nlocal := getproviders.PackageLocalArchive(archivePath)\nwant, err := getproviders.PackageHash(local)","handlingStrategy":"type-guard","validationCode":"// Only local archive/dir locations are hashable.\nswitch loc.(type) {\ncase getproviders.PackageLocalArchive, getproviders.PackageLocalDir:\n    // safe to hash\ndefault:\n    return fmt.Errorf(\"location %T is not locally hashable; download first\", loc)\n}","typeGuard":"func isHashablePackageLocation(loc getproviders.PackageLocation) bool {\n    switch loc.(type) {\n    case getproviders.PackageLocalArchive, getproviders.PackageLocalDir:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["hashing","package-location","invariant"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}