hashicorp/terraform · error

can not read leafPassphraseBytes from %s

Error message

can not read leafPassphraseBytes from %s

What it means

Returned during InstancePrincipalWithCerts setup when getCertificateFileBytes fails to read the leaf passphrase file. The code first checks if a file named 'leaf_passphrase' exists (note: the stat check uses certsDir + '/leaf_passphrase' but the read uses certsDir + 'leaf_passphrase' without a separator — a likely path-joining bug in the source). If the stat succeeds but the read fails, this error is returned.

Source

Thrown at internal/backend/remote-state/oci/auth.go:215

			return nil, fmt.Errorf("can not get working directory for current os platform")
		}

		certsDir := filepath.Clean(getEnvSettingWithDefault("test_certificates_location", defaultCertsDir))
		leafCertificateBytes, err := getCertificateFileBytes(filepath.Join(certsDir, "ip_cert.pem"))
		if err != nil {
			return nil, fmt.Errorf("can not read leaf certificate from %s", filepath.Join(certsDir, "ip_cert.pem"))
		}

		leafPrivateKeyBytes, err := getCertificateFileBytes(filepath.Join(certsDir, "ip_key.pem"))
		if err != nil {
			return nil, fmt.Errorf("can not read leaf private key from %s", filepath.Join(certsDir, "ip_key.pem"))
		}

		leafPassphraseBytes := []byte{}
		if _, err := os.Stat(certsDir + "/leaf_passphrase"); !os.IsNotExist(err) {
			leafPassphraseBytes, err = getCertificateFileBytes(filepath.Join(certsDir + "leaf_passphrase"))
			if err != nil {
				return nil, fmt.Errorf("can not read leafPassphraseBytes from %s", filepath.Join(certsDir+"leaf_passphrase"))
			}
		}

		intermediateCertificateBytes, err := getCertificateFileBytes(filepath.Join(certsDir, "intermediate.pem"))
		if err != nil {
			return nil, fmt.Errorf("can not read intermediate certificate from %s", filepath.Join(certsDir, "intermediate.pem"))
		}

		intermediateCertificatesBytes := [][]byte{
			intermediateCertificateBytes,
		}

		cfg, err := auth.InstancePrincipalConfigurationWithCerts(common.StringToRegion(p.region), leafCertificateBytes, leafPassphraseBytes, leafPrivateKeyBytes, intermediateCertificatesBytes)
		if err != nil {
			return nil, err
		}
		logger.Debug(" Configuration provided by: %s", cfg)

View on GitHub (pinned to d32a084675)

Solutions

  1. Remove the leaf_passphrase file from the certs directory if your test cert has no passphrase — the code only attempts to read it when it exists.
  2. If a passphrase is needed, ensure the file is readable AND be aware of the path-joining bug: the file may need to exist at the path formed by certsDir+'leaf_passphrase' (no separator) rather than certsDir+'/leaf_passphrase'.
  3. Set test_certificates_location to a directory where the concatenation resolves correctly.
  4. Report the path-joining bug upstream (certsDir + 'leaf_passphrase' should be filepath.Join(certsDir, 'leaf_passphrase')).

Example fix

// before
// leaf_passphrase file exists, triggering read at buggy path

// after (if no passphrase needed):
rm $test_certificates_location/leaf_passphrase
terraform init

// NOTE: source has a bug: filepath.Join(certsDir+"leaf_passphrase") should be
// filepath.Join(certsDir, "leaf_passphrase") — the stat check uses '/leaf_passphrase'
// but the read uses 'leaf_passphrase' without separator.
Defensive patterns

Strategy: validation

Validate before calling

// Be aware of the path-joining bug in the source:
// stat checks: certsDir + "/leaf_passphrase"
// read checks: certsDir + "leaf_passphrase" (no separator)
// The safest approach: remove leaf_passphrase if not needed.
func validatePassphraseFile(certsDir string) error {
    passphrasePath := filepath.Join(certsDir, "leaf_passphrase")
    if _, err := os.Stat(passphrasePath); err == nil {
        // File exists — the code will try to read it.
        // Warn about the path-joining bug.
        log.Printf("WARNING: leaf_passphrase exists; source code has a path-joining bug that may cause read failure")
    }
    return nil
}

Try / catch

// Pre-check and remove if unnecessary:
p := filepath.Join(certsDir, "leaf_passphrase")
if _, err := os.Stat(p); err == nil {
    if !passphraseRequired {
        os.Remove(p) // avoid triggering the buggy read path
    }
}

Prevention

When it happens

Trigger: auth="InstancePrincipalWithCerts" is set, the file {certsDir}/leaf_passphrase exists (so the stat check passes), but reading it fails — or it succeeds at an unexpected path due to the missing path separator in the read call (certsDir + 'leaf_passphrase' vs certsDir + '/leaf_passphrase').

Common situations: A leaf_passphrase file exists in the certs dir but the path concatenation bug causes the read to look in the wrong location (parent directory); the file exists but has restrictive permissions; user accidentally created a leaf_passphrase file not realizing it triggers this code path.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/8ced2a7035a0c67c. Report an issue: GitHub.