hashicorp/terraform · critical · ErrChecksumDoesNotMatch

ErrChecksumDoesNotMatch

ErrChecksumDoesNotMatch

Error message

downloaded archive does not match the release checksum

What it means

ErrChecksumDoesNotMatch is a sentinel from ChecksumAuthentication.Authenticate: it computes the SHA-256 of the downloaded archive on disk and compares it byte-for-byte against the expected SHA256Hash. A mismatch means the bytes that arrived are not the bytes the checksum file (SHA256SUMS) attests to, indicating corruption or tampering after the checksum source was authenticated.

Source

Thrown at internal/releaseauth/checksum.go:28

	"fmt"
	"io"
	"log"
	"os"
)

// ChecksumAuthentication is an archive Authenticator that ensures a given file
// matches a SHA-256 checksum. It is important to verify the authenticity of the
// given checksum prior to using this Authenticator.
type ChecksumAuthentication struct {
	Authenticator

	expected        SHA256Hash
	archiveLocation string
}

// ErrChecksumDoesNotMatch is the error returned when the archive checksum does
// not match the given checksum.
var ErrChecksumDoesNotMatch = errors.New("downloaded archive does not match the release checksum")

// NewChecksumAuthentication creates an instance of ChecksumAuthentication with the given
// checksum and file location.
func NewChecksumAuthentication(expected SHA256Hash, archiveLocation string) *ChecksumAuthentication {
	return &ChecksumAuthentication{
		expected:        expected,
		archiveLocation: archiveLocation,
	}
}

func (a ChecksumAuthentication) Authenticate() error {
	f, err := os.Open(a.archiveLocation)
	if err != nil {
		return fmt.Errorf("failed to open downloaded archive: %w", err)
	}
	defer f.Close()

	h := sha256.New()

View on GitHub (pinned to c9def3e214)

Solutions

  1. Delete the cached/partial archive and re-download with `terraform init -upgrade` or by clearing the plugin cache.
  2. Verify the expected checksum actually corresponds to this archive version (re-fetch SHA256SUMS for the exact release).
  3. Disable or bypass any corporate proxy/mirror that may be altering bytes; confirm via a direct curl and sha256sum compare.
  4. Check free disk space and filesystem integrity if corruption is suspected.
  5. If both signature and checksum fail, treat as a potential supply-chain incident and re-verify against the publisher's published sums.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check is impossible (must hash the file first), but you can verify the
// expected checksum string is well-formed before constructing the Authenticator.
if _, err := releaseauth.SHA256FromHex(expectedHex); err != nil {
    return fmt.Errorf("bad expected checksum: %w", err)
}

Type guard

func isChecksumMismatch(err error) bool {
    return errors.Is(err, releaseauth.ErrChecksumDoesNotMatch)
}

Try / catch

if err := auth.Authenticate(); err != nil {
    if errors.Is(err, releaseauth.ErrChecksumDoesNotMatch) {
        // delete partial file and re-download once
        os.Remove(archiveLocation)
        return redownload()
    }
    return err
}

Prevention

When it happens

Trigger: Returned at internal/releaseauth/checksum.go:55 when bytes.Equal(gotHash, a.expected[:]) is false. The Authenticator is constructed via NewChecksumAuthentication(expected, archiveLocation) and is meant to run only after the expected checksum's authenticity is independently verified (e.g. by SignatureAuthentication).

Common situations: A truncated/partial download (network drop, disk full). A transparent proxy or corporate mirror rewriting the archive. Concurrent/aborted download leaving a partial file. A mismatched SHA256SUMS file used as the expected value. Disk/memory corruption. A man-in-the-middle that modified bytes (signature check should also then fail).

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/fe6b87bae5cf0c49. Report an issue: GitHub.