hashicorp/terraform · error

could not decode client certificate data: %v

Error message

could not decode client certificate data: %v

What it means

Raised in decodeCertificate (helpers.go:31-38), called from Backend.Configure when client_certificate is set. The value must be the base64-encoded bytes of a PKCS#12 (.pfx) bundle; this error means base64.StdEncoding.Decode rejected the string. Configure aborts before any network call. It is a pure input-validation error on the certificate value.

Source

Thrown at internal/backend/remote-state/azure/helpers.go:37

func logEntry(f string, v ...interface{}) {
	if os.Getenv("TF_LOG") == "" {
		return
	}

	if os.Getenv("TF_ACC") != "" {
		return
	}

	log.Printf(f, v...)
}

func decodeCertificate(clientCertificate string) ([]byte, error) {
	var pfx []byte
	if clientCertificate != "" {
		out := make([]byte, base64.StdEncoding.DecodedLen(len(clientCertificate)))
		n, err := base64.StdEncoding.Decode(out, []byte(clientCertificate))
		if err != nil {
			return pfx, fmt.Errorf("could not decode client certificate data: %v", err)
		}
		pfx = out[:n]
	}
	return pfx, nil
}

func getOidcToken(d *backendbase.SDKLikeData) (*string, error) {
	idToken := strings.TrimSpace(d.String("oidc_token"))

	if path := d.String("oidc_token_file_path"); path != "" {
		fileTokenRaw, err := os.ReadFile(path)

		if err != nil {
			return nil, fmt.Errorf("reading OIDC Token from file %q: %v", path, err)
		}

		fileToken := strings.TrimSpace(string(fileTokenRaw))

View on GitHub (pinned to c9def3e214)

Solutions

  1. Re-encode the PFX file as base64: base64 -w0 cert.pfx (Linux) or [Convert]::ToBase64String([IO.File]::ReadAllBytes('cert.pfx')) (PowerShell)
  2. Ensure no PEM headers / newlines are included — use the raw PFX bytes base64-encoded
  3. If you have a file path, use client_certificate_path instead of client_certificate
  4. Verify the base64 decodes: echo '<value>' | base64 -d | head -c4 | xxd (should start with PKCS magic bytes 30 82)

Example fix

# before: raw/PEM content in client_certificate (decoding fails)
export ARM_CLIENT_CERTIFICATE="-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"

# after: base64-encode the binary PFX
cert_b64=$(base64 -w0 cert.pfx)
export ARM_CLIENT_CERTIFICATE="$cert_b64"
# or, point at the file instead:
export ARM_CLIENT_CERTIFICATE_PATH="$PWD/cert.pfx"
Defensive patterns

Strategy: validation

Validate before calling

# Validate the client_certificate is decodable base64 (PKCS#12) before terraform init
validate_pfx_b64() {
  val="$1"
  [ -n "$val" ] || return 0
  # reject PEM-looking content
  case "$val" in *BEGIN*CERTIFICATE*) echo "FAIL: looks like PEM, not base64 PFX"; return 1;; esac
  decoded=$(printf '%s' "$val" | base64 -d 2>/dev/null) || { echo "FAIL: not valid base64 (error 159)"; return 1; }
  # PKCS#12 magic: 30 82
  printf '%s' "$val" | base64 -d | head -c2 | od -An -tx1 | grep -qi '30 82' \
    && echo "OK: valid base64 PFX" || echo "WARN: decoded but not PKCS#12 magic"
}
validate_pfx_b64 "$ARM_CLIENT_CERTIFICATE"

Prevention

When it happens

Trigger: Produced at helpers.go:35-37 when base64.StdEncoding.Decode fails on the client_certificate string. Triggered at 'terraform init' as soon as Configure parses the backend block.

Common situations: Pasting the raw (non-base64) PFX bytes; including PEM headers; a trailing newline or whitespace in the env var; copy truncation; using a file path instead of the encoded content (should use client_certificate_path for paths).

Understand the failure class

Related errors


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