{"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/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/cliconfig/credentials.go#L315-L351","documentation":"Thrown by CredentialsSource.updateLocalHostCredentials when ioutil.ReadFile fails to read the credentials JSON file (e.g. ~/.terraform.d/credentials.tfrc.json) with an error other than os.IsNotExist. It is the first I/O gate in updating a host's credentials: any read error that is not 'file does not exist' (permission denied, I/O error, path-too-long) is surfaced here before parsing.","triggerScenarios":"Calling any Terraform command that persists credentials (terraform login / logout, or the credentials helper update path) when the credentials file exists but is unreadable. Specifically: file mode bits deny read to the current uid; the path points to a directory; the volume is detached; or the file is on a network mount returning EIO.","commonSituations":"File created by a different user/root with 0600 perms so the running user cannot read it; TF_CLI_CONFIG_FILE or TF_CREDENTIALS pointing at a stale path; a previous crash left a half-named file; container volume mount permission mismatch.","solutions":["Verify the path Terraform resolves for the credentials file: run `terraform -help` style debugging or print s.CredentialsFilePath() — usually ~/.terraform.d/credentials.tfrc.json or $TF_CLI_CONFIG_FILE/credentials.tfrc.json.","Check permissions/ownership: `ls -l <path>` and `stat <path>`; ensure the current uid can read it (chmod u+r or chown).","Confirm the path is a regular file, not a directory or broken symlink (`readlink -f <path>`).","If the file is corrupt/unwanted, back it up and remove it so Terraform recreates it on next login."],"exampleFix":"// before: file owned by root, user cannot read\n// $ sudo chown $USER:$USER ~/.terraform.d/credentials.tfrc.json\n// $ chmod 600 ~/.terraform.d/credentials.tfrc.json\n// after: terraform login succeeds and updateLocalHostCredentials reads the file","handlingStrategy":"validation","validationCode":"// Before calling any credentials-updating path, confirm the file is readable\nfunc credentialsFileReadable(path string) error {\n    fi, err := os.Stat(path)\n    if os.IsNotExist(err) {\n        return nil // not-exist is tolerated by updateLocalHostCredentials\n    }\n    if err != nil {\n        return fmt.Errorf(\"stat %s: %w\", path, err)\n    }\n    if fi.IsDir() {\n        return fmt.Errorf(\"%s is a directory, not a credentials file\", path)\n    }\n    f, err := os.Open(path)\n    if err != nil {\n        return fmt.Errorf(\"%s not readable: %w\", path, err)\n    }\n    f.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run Terraform as the user who owns ~/.terraform.d/credentials.tfrc.json.","Never chmod the credentials file to deny its owner read access.","Set TF_CLI_CONFIG_FILE to an explicit, owned, regular file in automation."],"tags":["credentials","filesystem","permissions","terraform-cli","config"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}