hashicorp/terraform · error
failed to append certs
Error message
failed to append certs
What it means
Returned by configureTLS (internal/backend/remote-state/http/backend.go:294) when tlsConfig.RootCAs.AppendCertsFromPEM([]byte(clientCACertificatePem)) returns false. AppendCertsFromPEM returns false when the provided PEM data contains no parseable certificates, so the http backend refuses to configure a trust store built from garbage. This only triggers when client_ca_certificate_pem (or TF_HTTP_CLIENT_CA_CERTIFICATE_PEM) is set.
Source
Thrown at internal/backend/remote-state/http/backend.go:294
return fmt.Errorf("client_certificate_pem is set but client_private_key_pem is not")
}
if clientPrivateKeyPem != "" && clientCertificatePem == "" {
return fmt.Errorf("client_private_key_pem is set but client_certificate_pem is not")
}
// TLS configuration is needed; create an object and configure it
var tlsConfig tls.Config
client.HTTPClient.Transport.(*http.Transport).TLSClientConfig = &tlsConfig
if skipCertVerification {
// ignores TLS verification
tlsConfig.InsecureSkipVerify = true
}
if clientCACertificatePem != "" {
// trust servers based on a CA
tlsConfig.RootCAs = x509.NewCertPool()
if !tlsConfig.RootCAs.AppendCertsFromPEM([]byte(clientCACertificatePem)) {
return errors.New("failed to append certs")
}
}
if clientCertificatePem != "" && clientPrivateKeyPem != "" {
// attach a client certificate to the TLS handshake (aka mTLS)
certificate, err := tls.X509KeyPair([]byte(clientCertificatePem), []byte(clientPrivateKeyPem))
if err != nil {
return fmt.Errorf("cannot load client certificate: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{certificate}
}
return nil
}
func (b *Backend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
if name != backend.DefaultStateName {View on GitHub (pinned to c9def3e214)
Solutions
- Provide the full, valid PEM-encoded CA certificate chain in client_ca_certificate_pem (BEGIN CERTIFICATE ... END CERTIFICATE).
- Validate the PEM decodes to at least one x509 certificate before configuring the backend.
- If the content is a path, read the file and inline its contents into the attribute.
Example fix
// before: malformed/empty CA pem
backend "http" {
address = "https://state.example"
client_ca_certificate_pem = ""
}
// after: full PEM body
backend "http" {
address = "https://state.example"
client_ca_certificate_pem = <<-EOT
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUM...full CA cert...
-----END CERTIFICATE-----
EOT
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the PEM before configuring the backend.
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM([]byte(caPem)) {
return fmt.Errorf("client_ca_certificate_pem contains no parseable certificates")
} Prevention
- Inline the full PEM body (BEGIN/END CERTIFICATE), not a file path.
- Validate PEM decodes to at least one cert with x509.NewCertPool().AppendCertsFromPEM before use.
- Prefer loading CA bundles via a known-good source rather than hand-pasting.
When it happens
Trigger: Configuring the http backend with client_ca_certificate_pem set to a value that is not valid PEM, is truncated, contains only a private key, or has non-certificate PEM blocks; or TF_HTTP_CLIENT_CA_CERTIFICATE_PEM pointing at malformed content.
Common situations: Pasting only the human-readable header of a CA cert; copying an intermediate/key instead of the CA; trailing/leading whitespace or encoding corruption from env var transport; using a file path instead of inline PEM content (the field expects the PEM text, not a path).
Related errors
- default workspace not supported You can create a new workspa
- the secret name %v is invalid, {validationErrors} This is a
- address argument is required
- failed to parse address URL: %s
- address must be HTTP or HTTPS
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/8c3320675d8c03b5.
Report an issue: GitHub.