hashicorp/terraform · error
hash string must start with a scheme keyword followed by a c
Error message
hash string must start with a scheme keyword followed by a colon
What it means
From ParseHash in the providerreqs package. A Hash must begin with a non-empty alphanumeric scheme followed by a colon (e.g. 'h1:...', 'zh:...'). ParseHash finds the first ':' via strings.Index; if there is no colon, or the colon is at index 0 (empty scheme), it returns this error and NilHash. The function intentionally accepts UNKNOWN schemes (so it can ignore future schemes), but it rejects schemeless strings outright.
Source
Thrown at internal/getproviders/providerreqs/hash.go:48
// ParseHash parses the string representation of a Hash into a Hash value.
//
// A particular version of Terraform only supports a fixed set of hash schemes,
// but this function intentionally allows unrecognized schemes so that we can
// silently ignore other schemes that may be introduced in the future. For
// that reason, the Scheme method of the returned Hash may return a value that
// isn't in one of the HashScheme constants in this package.
//
// This function doesn't verify that the value portion of the given hash makes
// sense for the given scheme. Invalid values are just considered to not match
// any packages.
//
// If this function returns an error then the returned Hash is invalid and
// must not be used.
func ParseHash(s string) (Hash, error) {
colon := strings.Index(s, ":")
if colon < 1 { // 1 because a zero-length scheme is not allowed
return NilHash, fmt.Errorf("hash string must start with a scheme keyword followed by a colon")
}
return Hash(s), nil
}
// MustParseHash is a wrapper around ParseHash that panics if it returns an
// error.
func MustParseHash(s string) Hash {
hash, err := ParseHash(s)
if err != nil {
panic(err.Error())
}
return hash
}
// Scheme returns the scheme of the recieving hash. If the receiver is not
// using valid syntax then this method will panic.
func (h Hash) Scheme() HashScheme {
colon := strings.Index(string(h), ":")View on GitHub (pinned to c9def3e214)
Solutions
- Prefix the value with the correct scheme: 'h1:' for content hashes (PackageHashV1) or 'zh:' for legacy zip SHA256 hashes.
- Do not create Hash values by direct conversion; use HashScheme1.New(value) / HashSchemeZip.New(value) or ParseHash on a known-good string.
- If the value came from a lock file, delete the hash entry and regenerate it with 'terraform init'.
- Validate hash strings with ParseHash before persisting them, so malformed values are caught at write time.
Example fix
// before
h, err := providerreqs.ParseHash("9c7f8a2b...") // raw hex, no scheme
// after
h, err := providerreqs.ParseHash("h1:9c7f8a2b...")
// or construct correctly
h := providerreqs.HashScheme1.New("9c7f8a2b...") Defensive patterns
Strategy: validation
Validate before calling
// Validate every hash string at the boundary where it enters your system.
func validateHashes(hs []string) error {
for _, s := range hs {
if _, err := providerreqs.ParseHash(s); err != nil {
return fmt.Errorf("invalid hash %q: %w", s, err)
}
}
return nil
} Type guard
// Type guard for already-parsed Hash values vs raw strings.
func isValidHash(s string) bool {
_, err := providerreqs.ParseHash(s)
return err == nil
} Prevention
- Never build Hash by string concatenation; use HashScheme.New.
- Validate hash strings before writing them to lock files or API responses.
- Use ParseHash (not direct conversion) at every trust boundary.
When it happens
Trigger: ParseHash(s) called with a string that has no ':' or starts with ':'. Triggered when code reads a hash from a lock file, API response, or user input that is a bare hex digest (e.g. 'abcdef0123...') instead of a schemed hash like 'h1:abcdef...'.
Common situations: A .terraform.lock.hcl edited by hand where someone pasted a raw SHA256 without the 'h1:'/'zh:' prefix. A custom registry/mirror returning a plain hex checksum instead of a schemed hash. Code that constructs a Hash by string conversion instead of using HashScheme.New. A truncated hash value that lost its prefix.
Related errors
- ErrInvalidSHA256Hash
- must be eight hexadecimal digits
- invalid source address: %s
- can't use local directory %q as a module registry address
- this version of Terraform does not support any of the checks
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/9fa97a7bde5fc0a8.
Report an issue: GitHub.