JuliusBrussee/caveman · error

: certificate is unparseable, so the bundle is incomplete…

Error message

%s: certificate %d is unparseable, so the bundle is incomplete and must not be half-trusted: %w

What it means

Certificates parses a PEM file at path; when a CERTIFICATE block's DER bytes fail x509.ParseCertificate, it fails closed instead of skipping the bad entry, since trusting the remaining certs would make the bundle incomplete and half-trusted. The error names the file, the 1-based certificate position, and wraps the underlying parse error.

Solutions

  1. Verify each PEM block with `openssl x509 -in bundle.pem` per block (or `openssl crl2pkcs7 -nocrl -certfile bundle.pem | openssl pkcs7 -print_certs`) to find the corrupt certificate.
  2. Re-export/re-download the offending certificate from its source; replace the file rather than editing base64 by hand.
  3. Check the number of certs (openssl grep -c 'BEGIN CERTIFICATE') against what the CA provided; a truncated copy/paste is the usual culprit.
  4. If the file is actually a private key or CSR, obtain the correct certificate file and update the configured path.

Example fix

// before
roots, err := cabundle.PoolOf(mustParse("/etc/certs/bundle.pem")) // cert #2 corrupt
// after
// regenerate bundle from known-good certs:
//   cat root.pem intermediate.pem > bundle.pem && openssl x509 -in bundle.pem -noout
roots, err := cabundle.PoolOf(certs)
if err != nil { return fmt.Errorf("tls setup: %w", err) }
Defensive patterns

Strategy: validation

Validate before calling

func validateBundle(path string) error {
    data, err := os.ReadFile(path)
    if err != nil { return err }
    rest := data
    for {
        var block *pem.Block
        block, rest = pem.Decode(rest)
        if block == nil { break }
        if block.Type != "CERTIFICATE" { continue }
        if _, err := x509.ParseCertificate(block.Bytes); err != nil {
            return fmt.Errorf("%s has a corrupt certificate: %w", path, err)
        }
    }
    return nil
}
// call validateBundle before cabundle.Certificates/PoolOf

Try / catch

certs, err := cabundle.Certificates(path)
if err != nil && strings.Contains(err.Error(), "unparseable") {
    return fmt.Errorf("TLS bundle %s is corrupt; regenerate it from the CA source: %w", path, err)
}

Prevention

When it happens

Trigger: Calling Certificates (or Pool/loadRootCAs which call it) on a PEM file containing a block labeled CERTIFICATE whose bytes are corrupt, truncated, or not DER (e.g. the file contains a PRIVATE KEY body mislabeled, or was mangled by copy-paste/encoding conversion).

Common situations: Mounting a truncated Kubernetes secret or ConfigMap; a cert file saved with Windows line-ending or base64 re-encoding corruption; concatenating a full-chain file where one intermediate was cut off mid-base64; passing a private key file where a certificate was expected.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/af609a56bde79eeb. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/cabundle/cabundle.go:69

func Certificates(path string) ([]*x509.Certificate, error) {
	bundle, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var certs []*x509.Certificate
	rest := bundle
	for {
		var block *pem.Block
		block, rest = pem.Decode(rest)
		if block == nil {
			break
		}
		if block.Type != "CERTIFICATE" {
			continue
		}
		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("%s: certificate %d is unparseable, so the bundle is incomplete and must not be half-trusted: %w", path, len(certs)+1, err)
		}
		certs = append(certs, cert)
	}
	if bytes.Contains(rest, []byte("-----BEGIN")) {
		return nil, fmt.Errorf("%s: trailing PEM block is truncated after %d certificate(s), so the bundle is incomplete and must not be half-trusted", path, len(certs))
	}
	if len(certs) == 0 {
		return nil, fmt.Errorf("%s contains no valid PEM certificate", path)
	}
	return certs, nil
}

View on GitHub (pinned to 3ee70a1026)