{"record":{"id":"6f7c6c07f35bbca8","repo":"hashicorp/terraform","slug":"error-reading-s-s","errorCode":null,"errorMessage":"Error reading %s: %s","messagePattern":"Error reading (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/cliconfig/cliconfig.go","lineNumber":160,"sourceCode":"\t\tconfig = envConfig.Merge(config)\n\t}\n\n\tdiags = diags.Append(config.Validate())\n\n\treturn config, diags\n}\n\n// loadConfigFile loads the CLI configuration from \".terraformrc\" files.\nfunc loadConfigFile(path string) (*Config, tfdiags.Diagnostics) {\n\tvar diags tfdiags.Diagnostics\n\tresult := &Config{}\n\n\tlog.Printf(\"Loading CLI configuration from %s\", path)\n\n\t// Read the HCL file and prepare for parsing\n\td, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\tdiags = diags.Append(fmt.Errorf(\"Error reading %s: %s\", path, err))\n\t\treturn result, diags\n\t}\n\n\t// Parse it\n\tobj, err := hcl.Parse(string(d))\n\tif err != nil {\n\t\tdiags = diags.Append(fmt.Errorf(\"Error parsing %s: %s\", path, err))\n\t\treturn result, diags\n\t}\n\n\t// Build up the result\n\tif err := hcl.DecodeObject(&result, obj); err != nil {\n\t\tdiags = diags.Append(fmt.Errorf(\"Error parsing %s: %s\", path, err))\n\t\treturn result, diags\n\t}\n\n\t// Deal with the provider_installation block, which is not handled using\n\t// DecodeObject because its structure is not compatible with the","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/command/cliconfig/cliconfig.go#L142-L178","documentation":"Emitted by `loadConfigFile` (cliconfig.go:160) when `ioutil.ReadFile(path)` fails on a CLI config file (`.terraformrc` / `terraform.rc` or a `*.tfrc`/`*.tfrc.json` file). The `%s` placeholders are the file path and the wrapped OS read error. This is distinct from a missing file (handled earlier via `os.Stat`), so it indicates a real I/O failure on a file that exists.","triggerScenarios":"Terraform locates a CLI config file that exists but cannot be read — permission denied, file removed between stat and read, or an I/O error from the filesystem.","commonSituations":"`.terraformrc` with mode 000 or owned by another user; a symlink loop or broken symlink; NFS/network filesystem hiccup; `TF_CLI_CONFIG_FILE` pointing at an unreadable file.","solutions":["Check the file's permissions and ownership (`ls -l` on the path from the error) and make it readable.","Resolve any broken symlinks in the config path.","If the file is not meant to be used, unset `TF_CLI_CONFIG_FILE`/`TERRAFORM_CONFIG` or move/remove the file.","Retry if the error indicates a transient network/filesystem I/O fault."],"exampleFix":"# before\nls -l ~/.terraformrc   # -rw------- but owned by another user\nterraform init\n# Error reading /home/user/.terraformrc: permission denied\n\n# after\nchmod u+r ~/.terraformrc   # or chown to current user","handlingStrategy":"try-catch","validationCode":"// Pre-check readability of the CLI config file before loading it.\nfunc configReadable(path string) error {\n    f, err := os.OpenFile(path, os.O_RDONLY, 0)\n    if err != nil {\n        return fmt.Errorf(\"cannot read CLI config %s: %w\", path, err)\n    }\n    return f.Close()\n}","typeGuard":null,"tryCatchPattern":"// cfg, diags := cliconfig.LoadConfig()\nif diags.HasErrors() {\n    for _, d := range diags {\n        if strings.HasPrefix(d.Description().Summary, \"Error reading\") {\n            // The path in the message names the unreadable file.\n            return handleUnreadableConfig(d)\n        }\n    }\n}","preventionTips":["Ensure `.terraformrc`/`*.tfrc` files are owner-readable.","Set `TF_CLI_CONFIG_FILE` to an explicit, verified path in automation.","Resolve broken symlinks in the config path."],"tags":["terraform","cli-config","io","permissions","hcl"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}