hashicorp/terraform · error · ErrInvalidModuleSource
ErrInvalidModuleSource
ErrInvalidModuleSource
Error message
not a valid registry module source
What it means
ErrInvalidModuleSource is a sentinel from the registry source parser (regsrc), returned by NewModule when the optional host prefix is present but is either not a valid friendly host or is one of the disallowed special-case hosts (github.com, bitbucket.org) that Terraform treats as direct VCS sources, not registry hosts.
Source
Thrown at internal/registry/regsrc/module.go:17
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package regsrc
import (
"errors"
"fmt"
"regexp"
"strings"
svchost "github.com/hashicorp/terraform-svchost"
"github.com/hashicorp/terraform/internal/addrs"
)
var (
ErrInvalidModuleSource = errors.New("not a valid registry module source")
// nameSubRe is the sub-expression that matches a valid module namespace or
// name. It's strictly a super-set of what GitHub allows for user/org and
// repo names respectively, but more restrictive than our original repo-name
// regex which allowed periods but could cause ambiguity with hostname
// prefixes. It does not anchor the start or end so it can be composed into
// more complex RegExps below. Alphanumeric with - and _ allowed in non
// leading or trailing positions. Max length 64 chars. (GitHub username is
// 38 max.)
nameSubRe = "[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?"
// providerSubRe is the sub-expression that matches a valid provider. It
// does not anchor the start or end so it can be composed into more complex
// RegExps below. Only lowercase chars and digits are supported in practice.
// Max length 64 chars.
providerSubRe = "[0-9a-z]{1,64}"
// moduleSourceRe is a regular expression that matches the basicView on GitHub (pinned to c9def3e214)
Solutions
- For GitHub/Bitbucket, use the direct Git source form: `source = "git::https://github.com/USER/REPO.git"` or the shorthand `github.com/USER/REPO`, not as a registry host.
- For a registry module, drop the disallowed host or use a real registry hostname (e.g. `terraform.example.com/namespace/name/provider`).
- Validate the host string contains only allowed hostname characters and a real TLD.
- Double-check moduleSourceRe format: namespace/name/provider with optional //submodule.
Example fix
// before (treats github.com as registry host -> ErrInvalidModuleSource)
module "x" {
source = "github.com/myorg/network/vpc"
}
// after (explicit git source)
module "x" {
source = "git::https://github.com/myorg/network.git//vpc?ref=v1.2.0"
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate a registry module source before NewModule.
var regSrcRe = regexp.MustCompile(`^([A-Za-z0-9.-]+\.[A-Za-z]{2,}/)?[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?/[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?/[0-9a-z]{1,64}(//.*)?$`)
func looksLikeRegistry(src string) bool { return regSrcRe.MatchString(src) } Type guard
func isInvalidModuleSource(err error) bool {
return errors.Is(err, regsrc.ErrInvalidModuleSource)
} Try / catch
m, err := regsrc.NewModule(host, ns, name, provider, sub)
if errors.Is(err, regsrc.ErrInvalidModuleSource) {
if host == "github.com" || host == "bitbucket.org" {
// user meant a direct git source
return gitSource(host, ns, name)
}
return fmt.Errorf("invalid registry host %q", host)
} Prevention
- Never use github.com/bitbucket.org as a registry host prefix; use direct git sources for those.
- Validate module source strings with moduleSourceRe before parsing.
- Document the namespace/name/provider format for your team.
When it happens
Trigger: Returned at internal/registry/regsrc/module.go:88 inside NewModule when host != "" and the parsed FriendlyHost is either !h.Valid() or disallowed[h.Display()] is true. The disallowed set is {github.com, bitbucket.org}.
Common situations: Writing a module source like `github.com/foo/bar/baz` expecting registry semantics, or `[github.com]/namespace/name/provider`. Malformed host with invalid characters. Confusing a Git source (`github.com/user/repo`) with a registry source (`hostname/namespace/name/provider`).
Related errors
- can't use local directory %q as a module registry address
- Registry returned provider with type %q, expected %q
- empty state name
- Attempted to initialize pluggable state with an empty string
- missing state name
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/12dea44923b88cc1.
Report an issue: GitHub.