hashicorp/terraform · error
cannot read %s: %s
Error message
cannot read %s: %s
What it means
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.
Source
Thrown at internal/command/cliconfig/credentials.go:333
default:
// Should never happen because the above cases are exhaustive
return fmt.Errorf("invalid credentials location %#v", loc)
}
}
func (s *CredentialsSource) updateLocalHostCredentials(host svchost.Hostname, new svcauth.HostCredentialsWritable) error {
// This function updates the local credentials file in particular,
// regardless of whether a credentials helper is active. It should be
// called only indirectly via updateHostCredentials.
filename, err := s.CredentialsFilePath()
if err != nil {
return fmt.Errorf("unable to determine credentials file path: %s", err)
}
oldSrc, err := ioutil.ReadFile(filename)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot read %s: %s", filename, err)
}
var raw map[string]interface{}
if len(oldSrc) > 0 {
// When decoding we use a custom decoder so we can decode any numbers as
// json.Number and thus avoid losing any accuracy in our round-trip.
dec := json.NewDecoder(bytes.NewReader(oldSrc))
dec.UseNumber()
err = dec.Decode(&raw)
if err != nil {
return fmt.Errorf("cannot read %s: %s", filename, err)
}
} else {
raw = make(map[string]interface{})
}
rawCredsI, ok := raw["credentials"]View on GitHub (pinned to c9def3e214)
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.
Example fix
# before ls -l ~/.terraform.d/credentials.tfrc.json # no read perms terraform login # cannot read .../credentials.tfrc.json: permission denied # after chmod u+rw ~/.terraform.d/credentials.tfrc.json terraform login
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the credentials file is readable (ignoring NotExist) before update.
func credsFileReadable(path string) error {
_, err := os.ReadFile(path)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot read %s: %w", path, err)
}
return nil
} Try / catch
// if err := src.StoreForHost(host, creds); err != nil {
// if strings.Contains(err.Error(), "cannot read") &&
// !strings.Contains(err.Error(), "invalid value") {
// // permission / I/O error on credentials.tfrc.json (556)
// }
// } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Error reading %s: %s
- credentials file %s has invalid value for "credentials" prop
- cannot serialize updated credentials file: %s
- error deleting workspace %s: %w
- unable to build authorizer for Storage API: %+v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b02e217a0437d193.
Report an issue: GitHub.