How to Fix Terraform 'Failed to Query Available Provider Packages: Could Not Retrieve Source' Error
Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 15–45 mins
TL;DR
- What broke: Terraform's provider installer cannot reach
registry.terraform.ioor a configured private mirror, makingterraform initfail completely — no plan, no apply, full stop. - How to fix it: Validate your
sourceaddress inrequired_providers, check network egress rules, and audit your.terraformrc/terraform.rcfor malformedprovider_installationblocks. - Fast path: Use our Client-Side Sandbox below to auto-refactor this — paste your
terraformblock and CLI config, and get a corrected output without sending secrets to a third-party server.
The Incident (What Does the Error Mean?)
Raw error output:
Error: Failed to query available provider packages
│ Could not retrieve the list of available versions for provider
│ hashicorp/aws: could not retrieve source
│
│ Could not connect to registry.terraform.io: dial tcp: lookup
│ registry.terraform.io: no such host
or in air-gapped / mirror scenarios:
Error: Failed to query available provider packages
│ Could not retrieve the list of available versions for provider
│ hashicorp/aws: could not retrieve source
│
│ 3 problems:
│ - Unsuitable provider plugin: no available releases match
│ the given constraints
│ - Provider source address is not valid
│ - Failed to retrieve providers from mirror at
│ https://internal-mirror.corp.example.com
Immediate consequence: terraform init exits non-zero. Every downstream operation — plan, apply, validate — is dead. In a CI/CD pipeline, this fails the entire pipeline stage, blocks PRs, and stops deployments cold.
The Attack Vector / Blast Radius
This error is not just an inconvenience — it has a supply chain security dimension.
Scenario 1 — DNS/Network failure: Your runner or workstation cannot resolve registry.terraform.io. This is common in:
- VPC-isolated CI runners with no NAT gateway or missing security group egress rule on port 443.
- Corporate proxies that intercept TLS and present an untrusted cert, causing silent SSL failures.
- Kubernetes-based runners (GitLab Runner, Tekton) with broken CoreDNS upstream resolvers.
Scenario 2 — Malformed private mirror config: A broken provider_installation block in .terraformrc silently falls through or hard-fails. If your network_mirror URL returns a 403/404, Terraform does not fall back to the public registry by default when direct is excluded — all installs fail.
Scenario 3 — Typo in source address (supply chain risk): A misspelled source like hashcorp/aws instead of hashicorp/aws will resolve to a different namespace on the public registry. A malicious actor can publish a provider under a typo-squatted namespace. Terraform will happily download and execute it with full local system access.
Blast radius: Full deployment freeze across all environments sharing the broken config. In monorepos with shared provider blocks, this takes down every team simultaneously.
How to Fix It (The Solution)
Root Cause Checklist (Run in Order)
curl -v https://registry.terraform.io/v1/providers/hashicorp/aws/versions— confirms basic registry reachability.echo $HTTPS_PROXY && echo $NO_PROXY— confirms proxy config is not swallowing registry traffic.cat ~/.terraformrcor%APPDATA%\terraform.rc— confirms no broken mirror block.- Check
required_providerssource strings for typos.
Fix 1: Malformed or Missing required_providers Source
terraform {
required_providers {
- aws = {
- source = "aws"
- }
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.0"
+ }
}
}
Rule: Source must always be <namespace>/<type>. A bare "aws" is interpreted as registry.terraform.io/hashicorp/aws only by legacy fallback — do not rely on it.
Fix 2: Broken .terraformrc Network Mirror Block
provider_installation {
- network_mirror {
- url = "https://internal-mirror.corp.example.com"
- }
+ network_mirror {
+ url = "https://internal-mirror.corp.example.com/terraform-providers/"
+ include = ["registry.terraform.io/hashicorp/*"]
+ }
+ direct {
+ exclude = ["registry.terraform.io/hashicorp/*"]
+ }
}
Critical: The url must end with a trailing slash. The mirror must implement the Terraform Provider Network Mirror Protocol. Add a direct block explicitly to control fallback behavior — omitting it means Terraform may attempt direct registry access anyway, or may not, depending on version.
Fix 3: Proxy / TLS Interception
# In your CI environment variables or shell profile
-# (no proxy config set)
+export HTTPS_PROXY="http://proxy.corp.example.com:8080"
+export NO_PROXY="169.254.169.254,10.0.0.0/8"
+export SSL_CERT_FILE="/etc/ssl/certs/corp-ca-bundle.crt"
For Terraform specifically, also set:
+export TF_CLI_ARGS_init="-plugin-dir=/opt/terraform-plugins"
If you pre-download providers into a local plugin cache, you bypass the registry entirely for air-gapped builds.
Enterprise Best Practice: Filesystem Mirror + Artifact Repository
For production pipelines, never rely on live registry calls during terraform init:
# .terraformrc (enterprise pattern)
provider_installation {
- direct {}
+ filesystem_mirror {
+ path = "/opt/terraform/providers"
+ include = ["registry.terraform.io/*/*"]
+ }
+ direct {
+ exclude = ["registry.terraform.io/*/*"]
+ }
}
Providers are vendored into /opt/terraform/providers via a separate, audited pipeline stage that runs terraform providers mirror. This:
- Eliminates runtime registry dependency.
- Pins exact provider binaries (checksums enforced via
.terraform.lock.hcl). - Satisfies SOC2/FedRAMP requirements for third-party software vetting.
💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.
Prevention in CI/CD
1. Lock the Dependency Graph — Always Commit .terraform.lock.hcl
# In your Makefile or CI script
terraform providers lock \
-platform=linux_amd64 \
-platform=darwin_arm64
git add .terraform.lock.hcl
The lock file stores provider checksums. If the registry is unreachable, Terraform can still validate cached providers against known-good hashes.
2. Checkov — Detect Missing Version Constraints Pre-Commit
# .pre-commit-config.yaml
- repo: https://github.com/bridgecrewio/checkov
rev: 3.2.0
hooks:
- id: checkov
args: ["--check", "CKV_TF_1"] # Enforces pinned provider sources
CKV_TF_1 flags any required_providers block missing an explicit version constraint — the same configs most likely to pull unexpected or typo-squatted providers.
3. OPA/Conftest — Enforce Approved Provider Namespaces
# policy/providers.rego
package terraform.providers
allowed_namespaces := {"hashicorp", "aws", "datadog", "pagerduty"}
deny[msg] {
provider := input.configuration.provider_calls[_]
ns := split(provider.source, "/")[0]
not allowed_namespaces[ns]
msg := sprintf("Provider namespace '%v' is not in the approved list", [ns])
}
conftest test --policy policy/ plan.json
This blocks supply-chain attacks from typo-squatted namespaces at plan time, before any binary is downloaded.
4. Terraform Cloud / Enterprise — Private Registry
If you are on HCP Terraform or Terraform Enterprise, configure the private registry and set TF_TOKEN_app_terraform_io in CI. All provider resolution goes through your org's registry, which is audited, access-controlled, and does not depend on public internet reachability.
# Verify token is set in CI
echo $TF_TOKEN_app_terraform_io | wc -c # Should not be 0