{"record":{"id":"b6177ec3779e4056","repo":"hashicorp/terraform","slug":"can-t-use-local-directory-q-as-a-module-registry","errorCode":null,"errorMessage":"can't use local directory %q as a module registry address","messagePattern":"can't use local directory %q as a module registry address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getmodules/moduleaddrs/source_parsing.go","lineNumber":156,"sourceCode":"\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// ParseModuleSourceRegistry is a variant of ParseModuleSource which only\n// accepts module registry addresses, and will reject any other address type.\n//\n// Use this instead of ParseModuleSource if you know from some other surrounding\n// context that an address is intended to be a registry address rather than\n// some other address type, which will then allow for better error reporting\n// due to the additional information about user intent.\nfunc ParseModuleSourceRegistry(raw string) (addrs.ModuleSource, error) {\n\t// Before we delegate to the \"real\" function we'll just make sure this\n\t// doesn't look like a local source address, so we can return a better\n\t// error message for that situation.\n\tif isModuleSourceLocal(raw) {\n\t\treturn addrs.ModuleSourceRegistry{}, fmt.Errorf(\"can't use local directory %q as a module registry address\", raw)\n\t}\n\n\tsrc, err := tfaddr.ParseModuleSource(raw)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn addrs.ModuleSourceRegistry{\n\t\tPackage: src.Package,\n\t\tSubdir:  src.Subdir,\n\t}, nil\n}\n\nfunc parseModuleSourceRemote(raw string) (addrs.ModuleSourceRemote, error) {\n\tvar subDir string\n\traw, subDir = SplitPackageSubdir(raw)\n\tif strings.HasPrefix(subDir, \"../\") {\n\t\treturn addrs.ModuleSourceRemote{}, fmt.Errorf(\"subdirectory path %q leads outside of the module package\", subDir)\n\t}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/getmodules/moduleaddrs/source_parsing.go#L138-L174","documentation":"Thrown by ParseModuleSourceRegistry when the raw source matches the local-path check (isModuleSourceLocal). This variant is explicitly registry-only and rejects anything that looks like a filesystem path so it can give a clearer error than the generic registry parser would. The %q is the raw input.","triggerScenarios":"A caller that knows it expects a registry address (e.g. the module installation pipeline in registry mode) is handed a './local' or '../other' style path and refuses it up front.","commonSituations":"Configuration or flag meant to reference a registry module is given a local path by mistake; a wrapper tool always routes sources through the registry parser regardless of form; migrating from local to registry modules and forgetting to update one source.","solutions":["Replace the local path with a registry address: '<NAMESPACE>/<TYPE>/<PROVIDER>'.","If local is intended, call ParseModuleSource (the general parser) instead of ParseModuleSourceRegistry.","Check the calling context (CLI flag, config field) to confirm a registry address is genuinely required."],"exampleFix":"# before (registry context, local path)\nsource = \"./modules/vpc\"\n\n# after (registry address)\nsource = \"terraform-aws-modules/vpc/aws\"","handlingStrategy":"type-guard","validationCode":"// If the source might be local, do not route through ParseModuleSourceRegistry.\n// if isModuleSourceLocal(raw) {\n//     return ParseModuleSource(raw) // general parser instead\n// }","typeGuard":"// isLocalModuleSource narrows before choosing the parser.\n// func isLocalModuleSource(raw string) bool {\n//     return strings.HasPrefix(raw, \"./\") || strings.HasPrefix(raw, \"../\") || filepath.IsAbs(raw)\n// }","tryCatchPattern":null,"preventionTips":["Choose ParseModuleSource (general) when source type is unknown.","Reserve ParseModuleSourceRegistry for contexts that genuinely require a registry address.","Validate source strings in CI to catch local paths in registry-only fields."],"tags":["module-address","registry","validation"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}