Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for OpenTofu By James Joyner IV · · 8 min read Last reviewed Jul 2026

OpenTofu Error: 'Failed to download module' on tofu init

Quick answer

Fix OpenTofu's 'Failed to download module' error on tofu init: correct bad source URLs, missing Git refs, and credential problems so modules install cleanly.

  • #opentofu
  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

Stuck on this OpenTofu error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Exact Error Message


│ Error: Failed to download module

│   on main.tf line 5:
│    5:   module "network" {

│ Could not download module "network" (main.tf:5) source code from
│ "git::https://github.com/acme/tf-modules.git?ref=v1.4.0": error downloading
│ 'https://github.com/acme/tf-modules.git?ref=v1.4.0': /usr/bin/git exited with 128:
│ fatal: could not read Username for 'https://github.com': terminal prompts disabled

Other tails include reference not found (a bad ref), couldn't find remote ref, Authentication failed, or a registry not found for a namespace/name/provider source.

What It Means

When tofu init reaches a module block, it fetches that module’s source using go-getter: a public/private module registry, a Git URL, an HTTP archive, or a local path. Failed to download module means OpenTofu located the module block but could not retrieve its code — because the source address is wrong, the Git ref does not exist, or it lacks credentials to reach a private source.

This is an init-time configuration/connectivity error. No plan runs and no resources change; the fix is in the module source, the ref, or how credentials are supplied.

Common Causes

  • A typo or wrong scheme in the source (missing git:: prefix, wrong host, wrong path).
  • A ref that does not exist — a deleted tag, renamed branch, or wrong commit.
  • Private Git or registry access without configured credentials, so Git prompts and fails non-interactively.
  • Using the registry shorthand (namespace/name/provider) for a module that is not published there.
  • A local source = "./modules/x" path that does not exist relative to the calling module.

Diagnostic Commands

Reproduce with debug logging to see the exact go-getter/Git command and failure:

TF_LOG=DEBUG tofu init 2>&1 | tail -n 40

Check whether the Git ref actually exists on the remote:

git ls-remote --tags --heads https://github.com/acme/tf-modules.git

Confirm the module sources declared in your configuration:

tofu providers

Clear cached modules to force a fresh download attempt:

rm -rf .terraform/modules && tofu init

Step-by-Step Resolution

  1. Read the tail of the error. A 128 from Git usually means auth or a missing ref; a registry not found means the shorthand source is wrong.

  2. Fix the source and pin an existing ref. Use the git:: prefix for Git URLs and a tag you have confirmed exists:

module "network" {
  source = "git::https://github.com/acme/tf-modules.git//network?ref=v1.4.0"
}
  1. For private Git over HTTPS in CI, inject a token via a Git config rewrite so no interactive prompt is needed:
git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
tofu init
  1. For SSH sources, make sure an agent/key is available and switch the source to SSH:
module "network" {
  source = "git::ssh://git@github.com/acme/tf-modules.git//network?ref=v1.4.0"
}
  1. For a registry module, use the correct four- or three-part address and a version constraint instead of a Git URL:
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
}
  1. Re-run init and confirm the module installs:
tofu init
Downloading git::https://github.com/acme/tf-modules.git?ref=v1.4.0 for network...
OpenTofu has been successfully initialized!

If you need to restructure a monorepo of modules into clean sources, the OpenTofu module prompts can draft consistent source and ref conventions.

Prevention

  • Always pin modules to an immutable ref (tag or commit), never a moving branch, so an upstream change cannot break init.
  • Use the //subdir syntax to point at a subdirectory rather than assuming the repo root.
  • Configure private-source credentials once, at the CI level, using a Git insteadOf rewrite or SSH agent.
  • Prefer the module registry with a version constraint for well-known public modules; it is more stable than raw Git URLs.
  • Run tofu init in CI on pull requests so a broken source is caught before merge.
  • Failed to install provider — the same class of fetch problem, but for a provider plugin rather than a module.
  • Unreadable module directory — a local path source that exists but cannot be read.
  • Module not installed — you referenced a module but never ran tofu init to download it.
  • Reference to undeclared module — the module block name in an expression does not exist at all.

Frequently Asked Questions

Why does Git say ‘could not read Username’ in CI? Git tries to prompt for credentials but prompts are disabled non-interactively; supply a token via a url.insteadOf rewrite or use an SSH key instead.

How do I point at a subdirectory of a module repo? Use the double-slash syntax, for example source = "git::https://host/repo.git//path/to/module?ref=v1.0.0".

Should I pin modules to a branch or a tag? Always pin to a tag or commit; a branch can change under you and make a previously working init suddenly fail.

Why does the registry say ‘not found’ for my module? The namespace/name/provider shorthand only works for modules published to a registry; for a Git repo, use a git:: URL instead. For more module and init fixes, see the OpenTofu guides.

Free download · 368-page PDF

Fixed it? Get 500 OpenTofu & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.