hashicorp/terraform · error

Cannot read directory %s

Error message

Cannot read directory %s

What it means

Emitted by terraform fmt's processDir in the default branch of the os.ReadDir error switch — i.e. ReadDir failed for any reason OTHER than the path not existing (the not-exist case is handled separately at fmt.go:239). The raw error is intentionally simplified because ReadDir's messages are not end-user friendly. The %s is the normalized target path.

Source

Thrown at internal/command/fmt.go:243

	}

	return diags
}

func (c *FmtCommand) processDir(path string, stdout io.Writer) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	log.Printf("[TRACE] terraform fmt: looking for files in %s", path)

	entries, err := os.ReadDir(path)
	if err != nil {
		switch {
		case os.IsNotExist(err):
			diags = diags.Append(fmt.Errorf("There is no configuration directory at %s", path))
		default:
			// ReadDir does not produce error messages that are end-user-appropriate,
			// so we'll need to simplify here.
			diags = diags.Append(fmt.Errorf("Cannot read directory %s", path))
		}
		return diags
	}

	for _, info := range entries {
		name := info.Name()
		if configs.IsIgnoredFile(name) {
			continue
		}
		subPath := filepath.Join(path, name)
		if info.IsDir() {
			if c.recursive {
				subDiags := c.processDir(subPath, stdout)
				diags = diags.Append(subDiags)
			}

			// We do not recurse into child directories by default because we
			// want to mimic the file-reading behavior of "terraform plan", etc,

View on GitHub (pinned to c9def3e214)

Solutions

  1. Check and fix directory permissions: `chmod a+rx <dir>` (or grant the terraform process read+execute access).
  2. Confirm the path is actually a directory and not a file/symlink: `ls -ld <dir>`.
  3. If on a network/removable mount, verify the mount is healthy and read-write: `mount | grep <dir>`.
  4. Run terraform as a user that owns or has been granted access to the directory.

Example fix

# before
$ terraform fmt ./configs   # dir exists but unreadable
# after
$ chmod a+rx ./configs
$ terraform fmt ./configs
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the directory is readable+traversable by the current process.
if err := unix.Access(dir, unix.R_OK|unix.X_OK); err != nil {
    return fmt.Errorf("cannot read directory %q: %w; fix permissions first", dir, err)
}

Prevention

When it happens

Trigger: Running `terraform fmt <dir>` where the directory exists but cannot be read, most commonly due to insufficient POSIX permissions (missing read or execute bit on the directory). Also triggers on OS-level errors such as the path being a symlink loop, I/O errors from a failing disk, or the directory being a file/ special device instead of a directory.

Common situations: Directories created by another user with restrictive umask; running terraform as a non-owner; mounted filesystems that became read-only or failed; ACLs denying the current process. Containers where the bind-mounted directory lacks read access for the terraform process UID.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/cb6b6b1566d49660. Report an issue: GitHub.