OpenTofu Error: 'Failed to download module' on tofu init
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
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(missinggit::prefix, wrong host, wrong path). - A
refthat 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
-
Read the tail of the error. A
128from Git usually means auth or a missing ref; a registrynot foundmeans the shorthand source is wrong. -
Fix the
sourceand pin an existingref. Use thegit::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"
}
- 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
- 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"
}
- 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"
}
- 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
//subdirsyntax to point at a subdirectory rather than assuming the repo root. - Configure private-source credentials once, at the CI level, using a Git
insteadOfrewrite or SSH agent. - Prefer the module registry with a
versionconstraint for well-known public modules; it is more stable than raw Git URLs. - Run
tofu initin CI on pull requests so a broken source is caught before merge.
Related Errors
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 rantofu initto download it.Reference to undeclared module— themoduleblock 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.
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?
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.