hashicorp/terraform · warning

Option -write cannot be used when reading from stdin

Error message

Option -write cannot be used when reading from stdin

What it means

Thrown by FmtCommand.fmt when no path arguments are given (so input is assumed to come from stdin) AND the -write flag is set. Writing back to stdin is meaningless — you cannot overwrite a pipe — so Terraform refuses the combination. The user must either drop -write or supply a real file path.

Solutions

  1. Drop -write when reading from stdin: `terraform fmt < file.tf`.
  2. Or pass an explicit path so -write has somewhere to write: `terraform fmt -write file.tf`.
  3. If scripting, branch: use -write only when paths are provided.

Example fix

// before
//   cat main.tf | terraform fmt -write
// after (choose one):
//   cat main.tf | terraform fmt                 # stream, no write
//   terraform fmt -write main.tf                # in-place write to a file
Defensive patterns

Strategy: validation

Validate before calling

// In wrappers, only enable -write when real paths are present
func fmtArgs(write bool, paths []string) []string {
    args := []string{"fmt"}
    if write && len(paths) > 0 { args = append(args, "-write") }
    args = append(args, paths...)
    return args
}

Prevention

When it happens

Trigger: Running `terraform fmt -write` (or `-w`) with no file arguments, e.g. piping HCL through `cat config.tf | terraform fmt -write`. Also when -write is set globally and the user forgets to name a file.

Common situations: User wants to both format stdin output and persist it, forgetting stdin can't be written back; copy-pasting a `-w` habit into a pipe workflow; defaulting -write=true in a wrapper that sometimes runs without paths.

Related errors


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

Appendix: source

Thrown at internal/command/fmt.go:120

		if list {
			io.Copy(&cli.UiWriter{Ui: c.Ui}, buf)
		}
		if ok {
			return 0
		} else {
			return 3
		}
	}

	return 0
}

func (c *FmtCommand) fmt(paths []string, stdin io.Reader, stdout io.Writer) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	if len(paths) == 0 { // Assuming stdin, then.
		if c.write {
			diags = diags.Append(fmt.Errorf("Option -write cannot be used when reading from stdin"))
			return diags
		}
		fileDiags := c.processFile("<stdin>", stdin, stdout, true)
		diags = diags.Append(fileDiags)
		return diags
	}

	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 {

View on GitHub (pinned to d32a084675)