hashicorp/terraform · error
subdir %q not found
Error message
subdir %q not found
What it means
Raised by ExpandSubdirGlobs (internal/getmodules/moduleaddrs/subdir.go:89). This function expands a (possibly glob) subdir pattern against a real installed directory, typically after a registry-served archive is extracted. If filepath.Glob returns zero matches, the expected subdirectory is not present on disk.
Source
Thrown at internal/getmodules/moduleaddrs/subdir.go:89
// files on disk in the given directory which we assume contains the content
// of whichever package this is a subdirectory glob for.
//
// Subdir globs are used, for example, when a module registry wants to specify
// to select the contents of the single directory at the root of a conventional
// tar archive but it doesn't actually know the exact name of that directory.
// In that case it might specify a subdir of just "*", which this function
// will then expand into the single subdirectory found inside instDir, or
// return an error if the result would be ambiguous.
func ExpandSubdirGlobs(instDir string, subDir string) (string, error) {
pattern := filepath.Join(instDir, subDir)
matches, err := filepath.Glob(pattern)
if err != nil {
return "", err
}
if len(matches) == 0 {
return "", fmt.Errorf("subdir %q not found", subDir)
}
if len(matches) > 1 {
return "", fmt.Errorf("subdir %q matches multiple paths", subDir)
}
return matches[0], nil
}
View on GitHub (pinned to c9def3e214)
Solutions
- Clear the module cache and re-download/extract so the archive layout matches expectations.
- Verify the archive structure (it should contain a single top-level directory when the subdir is '*').
- Correct the subdir name in the source address to match a directory that actually exists in the package.
- If you control the publishing, repackage the module so the root contains exactly one directory.
Defensive patterns
Strategy: validation
Validate before calling
// Verify the expected subdir resolves before calling ExpandSubdirGlobs.
func subdirExists(instDir, subDir string) (string, error) {
pattern := filepath.Join(instDir, subDir)
matches, err := filepath.Glob(pattern)
if err != nil {
return "", err
}
if len(matches) == 0 {
return "", fmt.Errorf("subdir %q not found under %s", subDir, instDir)
}
return matches[0], nil
} Try / catch
resolved, err := moduleaddrs.ExpandSubdirGlobs(instDir, subDir)
if err != nil {
return fmt.Errorf("cannot resolve module subdir %q in %s: %w", subDir, instDir, err)
} Prevention
- Ensure module archives contain the expected directory layout (single top-level dir for '*').
- Clear and re-extract the module cache if the layout is unexpected.
- Use explicit subdir names rather than globs when the layout is known.
When it happens
Trigger: A registry module whose subdir spec (often '*') finds no top-level directory in the extracted archive, or a named subdir that does not exist, e.g. an archive whose contents sit at the root rather than inside a single directory.
Common situations: Non-standard archive layout (files at root instead of one wrapping directory); a typo'd subdir name in the source address; a partially extracted or corrupt cache; a registry returning an archive packed differently than expected.
Related errors
- subdir %q matches multiple paths
- Error parsing URL: %s
- can't use local directory %q as a module registry address
- subdirectory path %q leads outside of the module package
- detected subdirectory path %q of %q leads outside of the mod
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/7064cdead3eaac2b.
Report an issue: GitHub.