hashicorp/terraform · error

failed to append certs

Error message

failed to append certs

What it means

In NestingList or NestingSet mode, if MaxItems is set (non-zero, meaning a hard upper bound) then MinItems must not exceed it. A floor above the ceiling is an impossible constraint. When MaxItems is 0 it means unbounded, so the check is skipped.

Solutions

  1. Ensure MinItems <= MaxItems when MaxItems != 0.
  2. Set MaxItems: 0 if you want no upper limit.
  3. Lower MinItems or raise MaxItems so the range is satisfiable.

Example fix

// before
"items": { Nesting: configschema.NestingList, MinItems: 5, MaxItems: 3 },
// after
"items": { Nesting: configschema.NestingList, MinItems: 3, MaxItems: 5 },
Defensive patterns

Strategy: validation

Validate before calling

// In NestingList/NestingSet, MinItems must not exceed MaxItems (when MaxItems != 0).
func validRange(nb *configschema.NestedBlock) bool {
    switch nb.Nesting {
    case configschema.NestingList, configschema.NestingSet:
        return nb.MaxItems == 0 || nb.MinItems <= nb.MaxItems
    }
    return true
}

Type guard

func minLteMax(min, max int) bool { return max == 0 || min <= max }

Prevention

When it happens

Trigger: NestingList/NestingSet with MinItems: 5, MaxItems: 3. Guard at internal_validate.go:89 is `blockS.MinItems > blockS.MaxItems && blockS.MaxItems != 0`.

Common situations: Swapping min/max values when authoring the schema; computing limits from config where the floor overruns the cap; copy-paste from another block with different bounds.

Related errors


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

Appendix: 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 d32a084675)