hashicorp/terraform · warning

Failed to read file

Error message

Failed to read file %s

What it means

Thrown by FmtCommand.fmt when os.Open fails on a file that (a) exists per os.Stat and (b) matches a fmt-supported extension (.tf, .tfvars, .tftest.hcl). The comment notes os.Open's raw error is not end-user-friendly, so Terraform substitutes this generic message. The loop continues to other files.

Solutions

  1. Confirm read permission: `cat <path>` or `test -r <path> && echo ok`.
  2. chmod to grant read: `chmod u+r <path>`.
  3. If a race deleted the file, rerun after stabilizing the directory.
  4. Check SELinux/AppArmor for read denials (`ls -Z`, audit logs).

Example fix

// before: file is 0000, stat ok but open fails
//   $ chmod u+r main.tf
// after: terraform fmt main.tf succeeds
Defensive patterns

Strategy: validation

Validate before calling

func openable(p string) error {
    f, err := os.Open(p)
    if err != nil { return fmt.Errorf("%s not readable: %w", p, err) }
    f.Close()
    return nil
}

Prevention

When it happens

Trigger: Stat succeeded (file existed) but by the time Open ran the file was removed (TOCTOU race); the file's permissions allow stat but not read; the path is a broken symlink that stat resolved but open cannot follow; the file is a special device.

Common situations: File mode denies read to the user (stat ok, open EACCES); a concurrent process deleted the file between stat and open; symlink to a missing target where lstat/stat semantics differ; SELinux denying read.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/98518fcb474e12ec. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/fmt.go:146

	for _, path := range paths {
		path = c.normalizePath(path)
		info, err := os.Stat(path)
		if err != nil {
			diags = diags.Append(fmt.Errorf("No file or directory at %s", path))
			return diags
		}
		if info.IsDir() {
			dirDiags := c.processDir(path, stdout)
			diags = diags.Append(dirDiags)
		} else {
			fmtd := false
			for _, ext := range fmtSupportedExts {
				if strings.HasSuffix(path, ext) {
					f, err := os.Open(path)
					if err != nil {
						// Open does not produce error messages that are end-user-appropriate,
						// so we'll need to simplify here.
						diags = diags.Append(fmt.Errorf("Failed to read file %s", path))
						continue
					}

					fileDiags := c.processFile(c.normalizePath(path), f, stdout, false)
					diags = diags.Append(fileDiags)
					f.Close()

					// Take note that we processed the file.
					fmtd = true

					// Don't check the remaining extensions.
					break
				}
			}

			if !fmtd {
				diags = diags.Append(fmt.Errorf("Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt"))
				continue

View on GitHub (pinned to d32a084675)