siyuan-note/siyuan · error

failed to decode CA certificate PEM

Error message

failed to decode CA certificate PEM

What it means

ImportCABundle imports a CA certificate and key from PEM strings supplied by the user. This error means the CA certificate string could not be decoded into a PEM block — it is empty, not PEM-formatted, or missing the CERTIFICATE header/footer.

Solutions

  1. Supply the certificate in valid PEM form including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines
  2. Ensure you are passing the certificate (not the key) to caCertPEM
  3. Convert DER to PEM (openssl x509 -inform DER -in cert.der -out cert.pem) before importing
  4. Trim surrounding whitespace/BOM and verify the string is non-empty before calling

Example fix

// before
ImportCABundle("MIIDdzCCAl+g...", keyPEM) // raw DER/base64
// after
ImportCABundle("-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+g...\n-----END CERTIFICATE-----", keyPEM)
Defensive patterns

Strategy: validation

Validate before calling

const cert = caCertPEM.trim();
if (!cert.startsWith('-----BEGIN CERTIFICATE-----') || !cert.endsWith('-----END CERTIFICATE-----')) {
  throw new Error('caCertPEM must be PEM-encoded');
}

Type guard

function isPEMCertificate(s) {
  return typeof s === "string" && s.includes("-----BEGIN CERTIFICATE-----");
}

Try / catch

try {
  await importCABundle(certPEM, keyPEM);
} catch (e) {
  if (e.message.includes("decode CA certificate PEM")) {
    alert("Certificate must be PEM format with BEGIN/END lines");
  }
}

Prevention

When it happens

Trigger: Calling the import CA bundle API with caCertPEM that is empty, base64-encoded-only, DER binary, or missing BEGIN/END lines; pasting a key where the cert should go.

Common situations: Users copying a certificate from a browser export in DER format; omitting header/footer lines when pasting; uploading the private key file into the certificate field; trailing whitespace/encoding issues from clipboard.

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 siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/bda7bccf34ff81dc. Report an issue: GitHub.

Appendix: 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 9f775e8a12)