hashicorp/terraform · error

can't locate credentials file: %s

Error message

can't locate credentials file: %s

What it means

Emitted by `Config.CredentialsSource` (credentials.go:45) when `CredentialsConfigFile()` (which calls `ConfigDir()` then `filepath.Join`) returns an error — i.e. the user's config/home directory cannot be determined. The comment at credentials.go:43-44 notes this is very unlikely because a successfully loaded `Config` implies the dir was already found.

Source

Thrown at internal/command/cliconfig/credentials.go:45

// that the credentials source will use when asked to save or forget credentials
// and when a "credentials helper" program is not active.
func CredentialsConfigFile() (string, error) {
	configDir, err := ConfigDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(configDir, "credentials.tfrc.json"), nil
}

// CredentialsSource creates and returns a service credentials source whose
// behavior depends on which "credentials" and "credentials_helper" blocks,
// if any, are present in the receiving config.
func (c *Config) CredentialsSource(helperPlugins pluginDiscovery.PluginMetaSet) (*CredentialsSource, error) {
	credentialsFilePath, err := CredentialsConfigFile()
	if err != nil {
		// If we managed to load a Config object at all then we would already
		// have located this file, so this error is very unlikely.
		return nil, fmt.Errorf("can't locate credentials file: %s", err)
	}

	var helper svcauth.CredentialsSource
	var helperType string
	for givenType, givenConfig := range c.CredentialsHelpers {
		available := helperPlugins.WithName(givenType)
		if available.Count() == 0 {
			log.Printf("[ERROR] Unable to find credentials helper %q; ignoring", givenType)
			break
		}

		selected := available.Newest()

		helperSource := svcauth.HelperProgramCredentialsSource(selected.Path, givenConfig.Args...)
		helper = svcauth.CachingCredentialsSource(helperSource) // cached because external operation may be slow/expensive
		helperType = givenType

		// There should only be zero or one "credentials_helper" blocks. We

View on GitHub (pinned to c9def3e214)

Solutions

  1. Ensure `HOME` (Unix) or `APPDATA`/`USERPROFILE` (Windows) is set to a writable directory.
  2. Set `TF_CLI_CONFIG_FILE` to an explicit config path so `ConfigDir()` is bypassed where possible.
  3. Run Terraform as a user with a resolvable home directory.

Example fix

# before (container without HOME)
terraform login
# can't locate credentials file: $HOME is not defined

# after
export HOME=/tmp/tfhome
mkdir -p "$HOME/.terraform.d"
terraform login
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify a config/home dir is resolvable before login/apply.
func homeResolvable() error {
    if dir, err := cliconfig.ConfigDir(); err != nil {
        return fmt.Errorf("no config/home dir: %w; set HOME or TF_CLI_CONFIG_FILE", err)
    } else {
        return os.MkdirAll(dir, 0o755)
    }
}

Try / catch

// src, err := cfg.CredentialsSource(plugins)
if err != nil {
    if strings.Contains(err.Error(), "can't locate credentials file") {
        // fix HOME / TF_CLI_CONFIG_FILE and retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling `CredentialsSource(...)` when `ConfigDir()` fails: `$HOME` is unset on Unix, `%APPDATA%` unavailable on Windows, or the home-dir resolver returns an error.

Common situations: Running Terraform under a service account/container without `HOME` set; hardened environments that strip home-dir env vars; running embedded Terraform internals from a context with no user profile.

Related errors


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