siyuan-note/siyuan · error

failed to decode CA certificate PEM

Error message

failed to decode CA certificate PEM

What it means

Returned by ImportCABundle in kernel/util/cert.go when pem.Decode on the caCertPEM string returns a nil block — the input is not valid PEM (missing -----BEGIN/END----- markers, wrong label, empty, or corrupted). This is the first validation step before parsing the certificate.

Source

Thrown at kernel/util/cert.go:318

	defer keyFile.Close()

	keyDER, err := x509.MarshalECPrivateKey(privateKey)
	if err != nil {
		return err
	}

	if err = pem.Encode(keyFile, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}); err != nil {
		return err
	}

	return nil
}

// ImportCABundle imports a CA certificate and private key from PEM-encoded strings.
func ImportCABundle(caCertPEM, caKeyPEM string) error {
	certBlock, _ := pem.Decode([]byte(caCertPEM))
	if certBlock == nil {
		return fmt.Errorf("failed to decode CA certificate PEM")
	}

	caCert, err := x509.ParseCertificate(certBlock.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse CA certificate: %w", err)
	}

	if !caCert.IsCA {
		return fmt.Errorf("the provided certificate is not a CA certificate")
	}

	keyBlock, _ := pem.Decode([]byte(caKeyPEM))
	if keyBlock == nil {
		return fmt.Errorf("failed to decode CA private key PEM")
	}

	_, err = x509.ParseECPrivateKey(keyBlock.Bytes)
	if err != nil {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure caCertPEM is a full PEM bundle including `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` lines.
  2. If you have a DER cert, convert it first: `openssl x509 -in ca.der -inform DER -out ca.pem -outform PEM`.
  3. Validate the PEM with `openssl x509 -in ca.pem -noout -text` before importing.

Example fix

// before
ImportCABundle(derBase64Only, keyPEM) // -> failed to decode CA certificate PEM

// after
ImportCABundle("-----BEGIN CERTIFICATE-----\n" + encodedPEM + "\n-----END CERTIFICATE-----\n", keyPEM)
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the PEM decodes before importing.
if block, _ := pem.Decode([]byte(caCertPEM)); block == nil {
    return fmt.Errorf("ca cert is not valid PEM; include BEGIN/END CERTIFICATE markers")
}
return util.ImportCABundle(caCertPEM, caKeyPEM)

Prevention

When it happens

Trigger: Calling util.ImportCABundle(caCertPEM, caKeyPEM) with a caCertPEM that pem.Decode cannot parse. ImportCABundle is the entry point for supplying a custom local CA for TLS.

Common situations: Pasting only the base64 body without the PEM headers; supplying a DER (binary) cert instead of PEM; trailing/leading whitespace or copy-paste truncation; wrong PEM type label.

Understand the failure class

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/bda7bccf34ff81dc. Report an issue: GitHub.