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

  1. Check and fix permissions on the path from the error (`chmod u+rw`).
  2. Resolve broken symlinks in `~/.terraform.d/credentials.tfrc.json`.
  3. Ensure no other Terraform process holds the file, then retry.
  4. 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

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


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/b02e217a0437d193. Report an issue: GitHub.