{"record":{"id":"b02e217a0437d193","repo":"hashicorp/terraform","slug":"cannot-read-s-s","errorCode":null,"errorMessage":"cannot read %s: %s","messagePattern":"cannot read (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/cliconfig/credentials.go","lineNumber":333,"sourceCode":"\tdefault:\n\t\t// Should never happen because the above cases are exhaustive\n\t\treturn fmt.Errorf(\"invalid credentials location %#v\", loc)\n\t}\n}\n\nfunc (s *CredentialsSource) updateLocalHostCredentials(host svchost.Hostname, new svcauth.HostCredentialsWritable) error {\n\t// This function updates the local credentials file in particular,\n\t// regardless of whether a credentials helper is active. It should be\n\t// called only indirectly via updateHostCredentials.\n\n\tfilename, err := s.CredentialsFilePath()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to determine credentials file path: %s\", err)\n\t}\n\n\toldSrc, err := ioutil.ReadFile(filename)\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"cannot read %s: %s\", filename, err)\n\t}\n\n\tvar raw map[string]interface{}\n\n\tif len(oldSrc) > 0 {\n\t\t// When decoding we use a custom decoder so we can decode any numbers as\n\t\t// json.Number and thus avoid losing any accuracy in our round-trip.\n\t\tdec := json.NewDecoder(bytes.NewReader(oldSrc))\n\t\tdec.UseNumber()\n\t\terr = dec.Decode(&raw)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"cannot read %s: %s\", filename, err)\n\t\t}\n\t} else {\n\t\traw = make(map[string]interface{})\n\t}\n\n\trawCredsI, ok := raw[\"credentials\"]","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/command/cliconfig/credentials.go#L315-L351","documentation":"Emitted by `updateLocalHostCredentials` (credentials.go:333) when `ioutil.ReadFile(filename)` on `credentials.tfrc.json` fails for any reason OTHER than the file not existing (the `!os.IsNotExist(err)` guard). So the file is present but unreadable, or some non-ENOENT I/O error occurred.","triggerScenarios":"Storing/forgetting credentials (`terraform login`/`terraform logout`) when `credentials.tfrc.json` exists but cannot be read — permission denied, a broken symlink, or a filesystem I/O error.","commonSituations":"The credentials file was chmod'd to 000 or chown'd to root; a broken symlink; concurrent process holding an exclusive lock; network filesystem error.","solutions":["Check and fix permissions on the path from the error (`chmod u+rw`).","Resolve broken symlinks in `~/.terraform.d/credentials.tfrc.json`.","Ensure no other Terraform process holds the file, then retry.","If the file is corrupt/unreadable and you have no stored tokens, back it up and remove it so Terraform recreates it."],"exampleFix":"# before\nls -l ~/.terraform.d/credentials.tfrc.json   # no read perms\nterraform login\n# cannot read .../credentials.tfrc.json: permission denied\n\n# after\nchmod u+rw ~/.terraform.d/credentials.tfrc.json\nterraform login","handlingStrategy":"try-catch","validationCode":"// Verify the credentials file is readable (ignoring NotExist) before update.\nfunc credsFileReadable(path string) error {\n    _, err := os.ReadFile(path)\n    if err != nil && !os.IsNotExist(err) {\n        return fmt.Errorf(\"cannot read %s: %w\", path, err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// if err := src.StoreForHost(host, creds); err != nil {\n//     if strings.Contains(err.Error(), \"cannot read\") &&\n//        !strings.Contains(err.Error(), \"invalid value\") {\n//         // permission / I/O error on credentials.tfrc.json (556)\n//     }\n// }","preventionTips":["Keep `credentials.tfrc.json` owner-readable/writable (`0600`).","Avoid broken symlinks in `~/.terraform.d`.","Don't let multiple processes hold exclusive locks on the file."],"tags":["terraform","credentials","io","permissions","json"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}