hashicorp/terraform · error

Failed to refresh module manifest

Error message

Failed to refresh module manifest: %w

What it means

After the config loader initializes successfully, ModulesCommand.internalManifest calls loader.RefreshModules() to reconcile the on-disk module manifest with installed modules. A non-nil error here is wrapped and the manifest read is aborted. This is the refresh/install step, not the read step.

Solutions

  1. Run terraform init -upgrade to re-fetch and refresh module sources cleanly.
  2. Check network/registry access and credentials for any module source (git, registry, s3).
  3. Remove .terraform/modules and re-run terraform init to rebuild the manifest.
  4. Pin module source versions so refresh resolves deterministically.

Example fix

# before: refresh fails on stale manifest
# after
rm -rf .terraform/modules
terraform init
terraform modules
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight network/registry reachability for module sources.
if isGitSource(moduleSrc) && !gitReachable(moduleSrc) {
    return fmt.Errorf("module source unreachable: %s", moduleSrc)
}

Try / catch

// Module refresh failures are often transient (registry flakiness).
if refreshErr := loader.RefreshModules(); refreshErr != nil {
    time.Sleep(backoff)
    refreshErr = loader.RefreshModules() // one bounded retry
}

Prevention

When it happens

Trigger: loader.RefreshModules() returns an error — typically network failure reaching a module registry, a git source that cannot be cloned, a removed module version, or a corrupt manifest file under .terraform/modules.

Common situations: Running `terraform modules` after a partial/failed terraform init; module source URL changed or went private; offline environment without the modules cached; .terraform/modules/modules.json corrupted.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/8587b5693f174563. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/modules.go:138

	manifestWithRef := resolver.Resolve(config)

	// Render the new manifest with references
	return view.Display(*manifestWithRef)
}

// internalManifest will use the configuration loader to refresh and load the
// internal manifest.
func (c *ModulesCommand) internalManifest() (modsdir.Manifest, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	loader, err := c.initConfigLoader()
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to initialize config loader: %w", err))
		return nil, diags
	}

	if err = loader.RefreshModules(); err != nil {
		diags = diags.Append(fmt.Errorf("Failed to refresh module manifest: %w", err))
		return nil, diags
	}

	return loader.ModuleManifest(), diags
}

const modulesCommandHelp = `
Usage: terraform [global options] modules [options]

  Prints out a list of all declared Terraform modules and their resolved versions
  in a Terraform working directory.

Options:

  -json               If specified, output declared Terraform modules and
                      their resolved versions in a machine-readable format.

  -var 'foo=bar'      Set a value for one of the input variables in the root

View on GitHub (pinned to d32a084675)