hashicorp/terraform · error
can't use local directory %q as a module registry address
Error message
can't use local directory %q as a module registry address
What it means
Raised by ParseModuleSourceRegistry (internal/getmodules/moduleaddrs/source_parsing.go:156). This strict parser accepts ONLY registry addresses, so if the source begins with a local-path prefix (./, ../, .\, ..\) it is rejected outright with this message. The caller chose the registry-only parser but supplied a local relative path.
Source
Thrown at internal/getmodules/moduleaddrs/source_parsing.go:156
return true
}
}
return false
}
// ParseModuleSourceRegistry is a variant of ParseModuleSource which only
// accepts module registry addresses, and will reject any other address type.
//
// Use this instead of ParseModuleSource if you know from some other surrounding
// context that an address is intended to be a registry address rather than
// some other address type, which will then allow for better error reporting
// due to the additional information about user intent.
func ParseModuleSourceRegistry(raw string) (addrs.ModuleSource, error) {
// Before we delegate to the "real" function we'll just make sure this
// doesn't look like a local source address, so we can return a better
// error message for that situation.
if isModuleSourceLocal(raw) {
return addrs.ModuleSourceRegistry{}, fmt.Errorf("can't use local directory %q as a module registry address", raw)
}
src, err := tfaddr.ParseModuleSource(raw)
if err != nil {
return nil, err
}
return addrs.ModuleSourceRegistry{
Package: src.Package,
Subdir: src.Subdir,
}, nil
}
func parseModuleSourceRemote(raw string) (addrs.ModuleSourceRemote, error) {
var subDir string
raw, subDir = SplitPackageSubdir(raw)
if strings.HasPrefix(subDir, "../") {
return addrs.ModuleSourceRemote{}, fmt.Errorf("subdirectory path %q leads outside of the module package", subDir)
}View on GitHub (pinned to c9def3e214)
Solutions
- If local paths should be allowed, call ParseModuleSource (the general parser) instead of ParseModuleSourceRegistry.
- If only registry addresses are valid for your context, reject or re-route local paths upstream and surface a clearer message to the user.
- Ensure the input is a genuine registry address (namespace/name/system or host/namespace/name/system).
Example fix
// before
addr, err := moduleaddrs.ParseModuleSourceRegistry("./modules/foo")
// after
addr, err := moduleaddrs.ParseModuleSource("./modules/foo") Defensive patterns
Strategy: validation
Validate before calling
// Dispatch to the right parser based on whether the source is local.
func parseSource(raw string) (addrs.ModuleSource, error) {
for _, p := range []string{"./", "../", ".\\", "..\\"} {
if strings.HasPrefix(raw, p) {
// Local path: do NOT use the registry-only parser.
return moduleaddrs.ParseModuleSource(raw)
}
}
return moduleaddrs.ParseModuleSourceRegistry(raw)
} Try / catch
if _, err := moduleaddrs.ParseModuleSourceRegistry(raw); err != nil {
if strings.HasPrefix(raw, "./") || strings.HasPrefix(raw, "../") {
// Wrong parser for a local path; retry with the general parser.
return moduleaddrs.ParseModuleSource(raw)
}
return nil, err
} Prevention
- Use ParseModuleSource unless you specifically require registry-only semantics.
- Validate the input shape and route local paths away from the registry parser.
- Document which parser each code path expects to avoid misrouting.
When it happens
Trigger: Calling ParseModuleSourceRegistry("./modules/foo") or ParseModuleSourceRegistry("../shared/network"). Any string starting with a recognized local prefix trips this guard before registry parsing is attempted.
Common situations: A tool or code path that intentionally restricts inputs to registry addresses receiving a local path; user confusion between the general ParseModuleSource and the registry-only variant; misrouted input in a wrapper CLI.
Related errors
- invalid source address: %s
- ErrInvalidModuleSource
- ErrInvalidSHA256Hash
- must be eight hexadecimal digits
- URL is not a valid S3 URL
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b6177ec3779e4056.
Report an issue: GitHub.