siyuan-note/siyuan · error

failed to parse CA certificate

Error message

failed to parse CA certificate: %w

What it means

ImportCABundle accepts a CA certificate PEM and private key, validates them, and installs them into the workspace ConfDir as the TLS CA bundle. This error is returned when the PEM block decodes fine but x509.ParseCertificate rejects the DER bytes, so the certificate body is malformed or not an X.509 certificate.

Solutions

  1. Verify the file starts with -----BEGIN CERTIFICATE----- and re-export it with 'openssl x509 -in ca.crt -outform PEM'
  2. Check with 'openssl x509 -text -noout -in ca.crt' that the file parses as an X.509 certificate
  3. Regenerate the CA (e.g. with openssl req -x509 or the kernel's own CA generation) and re-import

Example fix

// before
caCertPEM := caKeyFileContents // wrong PEM (private key)
ImportCABundle(caCertPEM, caKeyPEM)
// after
caCertPEM := string(caCertFileContents) // -----BEGIN CERTIFICATE----- block
ImportCABundle(caCertPEM, caKeyPEM)
Defensive patterns

Strategy: validation

Validate before calling

func validCertPEM(pemStr string) bool {
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil || block.Type != "CERTIFICATE" { return false }
    _, err := x509.ParseCertificate(block.Bytes)
    return err == nil
}

Type guard

if block == nil || block.Type != "CERTIFICATE" { return errors.New("not a certificate PEM") }

Try / catch

if err := util.ImportCABundle(caCertPEM, caKeyPEM); err != nil {
    if strings.Contains(err.Error(), "failed to parse CA certificate") {
        // surface 'not a valid X.509 certificate' to the user
    }
}

Prevention

When it happens

Trigger: Calling ImportCABundle with caCertPEM whose first PEM block has a non-certificate type (e.g. 'PRIVATE KEY', 'CERTIFICATE REQUEST') or corrupted/truncated base64 DER payload.

Common situations: Pasting the wrong PEM file (the CA key instead of the CA cert), a certificate re-saved or truncated by a text editor, or a CSR/Public-key PEM copied from a CSR generation step.

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/6e4d265280282dd8. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/cert.go:323

	}

	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 {
		return fmt.Errorf("failed to parse CA private key: %w", err)
	}

	caCertPath := filepath.Join(ConfDir, TLSCACertFilename)
	caKeyPath := filepath.Join(ConfDir, TLSCAKeyFilename)

View on GitHub (pinned to 9f775e8a12)