siyuan-note/siyuan · error

failed to decode CA private key PEM

Error message

failed to decode CA private key PEM

What it means

After validating the CA certificate, ImportCABundle PEM-decodes the supplied private key. If pem.Decode returns no block, the key material is not valid PEM at all (no BEGIN/END delimiters or only whitespace/garbage), so the import fails before any key parsing.

Solutions

  1. Re-export the key in PEM form: 'openssl ec -in ca.key -out ca.key.pem'
  2. Ensure the text contains the full -----BEGIN ... PRIVATE KEY----- / -----END ... PRIVATE KEY----- block including newlines
  3. Check that you are passing the key file's contents, not the certificate file's, to ImportCABundle

Example fix

// before
caKeyPEM := "MHcCAQEEI..." // raw base64, no PEM armor
// after
caKeyPEM := "-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----\n"
Defensive patterns

Strategy: validation

Validate before calling

func validKeyPEM(pemStr string) bool {
    block, _ := pem.Decode([]byte(pemStr))
    return block != nil && strings.Contains(block.Type, "PRIVATE KEY")
}

Type guard

if block == nil || !strings.Contains(block.Type, "PRIVATE KEY") { return errors.New("not a private key PEM") }

Try / catch

if err := util.ImportCABundle(caCertPEM, caKeyPEM); err != nil {
    if strings.Contains(err.Error(), "failed to decode CA private key PEM") {
        // tell user the key text lacks PEM armor
    }
}

Prevention

When it happens

Trigger: Passing an empty string, a DER-encoded binary key, or text with the PEM headers stripped/renamed as caKeyPEM to ImportCABundle.

Common situations: Pasting the key from a 'openssl ec -outform DER' output, copying only the base64 body without the -----BEGIN EC PRIVATE KEY----- wrapper, or accidentally pasting the certificate again instead of the key.

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/224638877fc94350. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/cert.go:332

// 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)

	if err := os.WriteFile(caCertPath, []byte(caCertPEM), 0644); err != nil {
		return fmt.Errorf("failed to write CA certificate: %w", err)
	}

	if err := os.WriteFile(caKeyPath, []byte(caKeyPEM), 0600); err != nil {
		return fmt.Errorf("failed to write CA private key: %w", err)
	}

View on GitHub (pinned to 9f775e8a12)