diff --git a/internal/command/init.go b/internal/command/init.go index 415cbe06d96a..28c9d4740d95 100644 --- a/internal/command/init.go +++ b/internal/command/init.go @@ -756,6 +756,20 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State, // but rather just emit a single general message about it at // the end, by checking ctx.Err(). + case providercache.ErrChecksumMiss: + // This is a special kind of error that can often be fixed using + // the `terraform providers lock` command. We're just going to + // amend the actual error message with some extra information + // about how to fix this. + + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to install provider", + fmt.Sprintf("Error while installing %s v%s: %s\n\nUse the `terraform providers lock` command to include all necessary platforms in the dependency lock file. Ensure the current platform, %s, is included.", + provider.ForDisplay(), version, err.Msg, err.Meta.TargetPlatform.String(), + ), + )) + default: // We can potentially end up in here under cancellation too, // in spite of our getproviders.ErrRequestCanceled case above, diff --git a/internal/providercache/errors.go b/internal/providercache/errors.go new file mode 100644 index 000000000000..ac81e880a0a1 --- /dev/null +++ b/internal/providercache/errors.go @@ -0,0 +1,12 @@ +package providercache + +import "github.com/hashicorp/terraform/internal/getproviders" + +type ErrChecksumMiss struct { + Meta getproviders.PackageMeta + Msg string +} + +func (err ErrChecksumMiss) Error() string { + return err.Msg +} diff --git a/internal/providercache/package_install.go b/internal/providercache/package_install.go index 3aa776d02422..4566a4a608f6 100644 --- a/internal/providercache/package_install.go +++ b/internal/providercache/package_install.go @@ -116,10 +116,13 @@ func installFromLocalArchive(ctx context.Context, meta getproviders.PackageMeta, meta.Provider, meta.Version, meta.Location, err, ) } else if !matches { - return authResult, fmt.Errorf( - "the current package for %s %s doesn't match any of the checksums previously recorded in the dependency lock file", - meta.Provider, meta.Version, - ) + return authResult, ErrChecksumMiss{ + Meta: meta, + Msg: fmt.Sprintf( + "the current package for %s %s doesn't match any of the checksums previously recorded in the dependency lock file", + meta.Provider, meta.Version, + ), + } } } @@ -198,10 +201,13 @@ func installFromLocalDir(ctx context.Context, meta getproviders.PackageMeta, tar meta.Provider, meta.Version, meta.Location, err, ) } else if !matches { - return authResult, fmt.Errorf( - "the local package for %s %s doesn't match any of the checksums previously recorded in the dependency lock file (this might be because the available checksums are for packages targeting different platforms)", - meta.Provider, meta.Version, - ) + return authResult, ErrChecksumMiss{ + Meta: meta, + Msg: fmt.Sprintf( + "the local package for %s %s doesn't match any of the checksums previously recorded in the dependency lock file (this might be because the available checksums are for packages targeting different platforms)", + meta.Provider, meta.Version, + ), + } } }