hashicorp/terraform · error
Error reading
Error message
Error reading %s: %s
What it means
Thrown when Terraform cannot read a CLI configuration file (.terraformrc or .tfrc) at the filesystem level. ioutil.ReadFile returns an error which is wrapped with the file path. This is distinct from parsing errors (549, 550) — the file could not even be opened for reading.
Solutions
- Verify the config file path exists: ls -la <path>
- Check file permissions: chmod 644 ~/.terraformrc
- Ensure TF_CLI_CONFIG_FILE (if set) points to an existing, readable file
- Check for broken symlinks in the config path
Defensive patterns
Strategy: validation
Validate before calling
// Check config file exists and is readable before relying on it
func checkConfigFile(path string) error {
info, err := os.Stat(path)
if err != nil {
return fmt.Errorf("config file %s not accessible: %w", path, err)
}
if info.IsDir() {
return fmt.Errorf("config path %s is a directory, not a file", path)
}
return nil
} Prevention
- Verify TF_CLI_CONFIG_FILE points to an existing file
- Ensure ~/.terraformrc has read permissions for the running user
- Check for broken symlinks in the home directory path
- Use terraform's verbose logging (TF_LOG=DEBUG) to trace which config path is being read
When it happens
Trigger: loadConfigFile(path) calls ioutil.ReadFile(path) which fails because the file does not exist at the resolved path, permissions are denied, the path points to a directory, or an I/O error occurs.
Common situations: TF_CLI_CONFIG_FILE points to a nonexistent file; ~/.terraformrc has wrong permissions; file was deleted or moved; running as a different user whose HOME differs; broken symlinks in the config path.
Related errors
- cannot create temporary file to update credentials
- Cannot read directory
- cannot read
- cannot search
- cannot set mode for credentials file
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/6f7c6c07f35bbca8.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/cliconfig/cliconfig.go:160
config = envConfig.Merge(config)
}
diags = diags.Append(config.Validate())
return config, diags
}
// loadConfigFile loads the CLI configuration from ".terraformrc" files.
func loadConfigFile(path string) (*Config, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
result := &Config{}
log.Printf("Loading CLI configuration from %s", path)
// Read the HCL file and prepare for parsing
d, err := ioutil.ReadFile(path)
if err != nil {
diags = diags.Append(fmt.Errorf("Error reading %s: %s", path, err))
return result, diags
}
// Parse it
obj, err := hcl.Parse(string(d))
if err != nil {
diags = diags.Append(fmt.Errorf("Error parsing %s: %s", path, err))
return result, diags
}
// Build up the result
if err := hcl.DecodeObject(&result, obj); err != nil {
diags = diags.Append(fmt.Errorf("Error parsing %s: %s", path, err))
return result, diags
}
// Deal with the provider_installation block, which is not handled using
// DecodeObject because its structure is not compatible with theView on GitHub (pinned to d32a084675)