go-task/task · error

failed to parse CA certificate

Error message

failed to parse CA certificate

What it means

After reading the CA file, buildHTTPClient calls x509.AppendCertsFromPEM; if no certificates could be parsed from the data, the pool is empty and this error is returned. It means the file exists and is readable but contains no valid PEM certificates.

Source

Thrown at taskfile/node_http.go:52

	// If no TLS customization is needed, return the default client
	if !insecure && caCert == "" && cert == "" {
		return http.DefaultClient, nil
	}

	tlsConfig := &tls.Config{
		InsecureSkipVerify: insecure, //nolint:gosec
	}

	// Load custom CA certificate if provided
	if caCert != "" {
		caCertData, err := os.ReadFile(caCert)
		if err != nil {
			return nil, fmt.Errorf("failed to read CA certificate: %w", err)
		}
		caCertPool := x509.NewCertPool()
		if !caCertPool.AppendCertsFromPEM(caCertData) {
			return nil, fmt.Errorf("failed to parse CA certificate")
		}
		tlsConfig.RootCAs = caCertPool
	}

	// Load client certificate and key if provided
	if cert != "" && certKey != "" {
		clientCert, err := tls.LoadX509KeyPair(cert, certKey)
		if err != nil {
			return nil, fmt.Errorf("failed to load client certificate: %w", err)
		}
		tlsConfig.Certificates = []tls.Certificate{clientCert}
	}

	return &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
	}, nil

View on GitHub (pinned to 385e5ad92a)

Solutions

  1. Convert the certificate to PEM format: openssl x509 -inform DER -in ca.der -out ca.pem
  2. Open the file and verify it contains a -----BEGIN CERTIFICATE----- block
  3. Re-download/export the CA bundle (the file may be an HTML error page or truncated)
  4. Ensure you are pointing at the CA certificate, not a private key or CSR

Example fix

# before (DER export)
task --cacert ./corp-ca.cer ...
# after (PEM conversion)
openssl x509 -inform DER -in corp-ca.cer -out corp-ca.pem
task --cacert ./corp-ca.pem ...
Defensive patterns

Strategy: validation

Validate before calling

pemBytes, err := os.ReadFile(caPath)
if err != nil {
    return err
}
if !x509.NewCertPool().AppendCertsFromPEM(pemBytes) {
    return fmt.Errorf("%s contains no valid PEM certificates", caPath)
}

Type guard

func isValidPEMCert(path string) bool {
    b, err := os.ReadFile(path)
    if err != nil {
        return false
    }
    return x509.NewCertPool().AppendCertsFromPEM(b)
}

Try / catch

node, err := taskfile.NewHTTPNode(..., caCert, ...)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse CA certificate") {
        // convert to PEM or re-download the bundle, then retry
    }
    return err
}

Prevention

When it happens

Trigger: NewHTTPNode -> buildHTTPClient: caCert file read succeeds but AppendCertsFromPEM returns false — e.g. the file holds DER-encoded certs, a private key, HTML/error text, or an empty file.

Common situations: Downloading a CA over a captive portal that returns an HTML error page saved as the cert; exporting certs in DER instead of PEM format; pointing --cacert at a key file or a combined file whose cert block is malformed; truncated downloads.

Understand the failure class

Related errors


AI-assisted analysis of go-task/task@385e5ad92a (2026-09-05). Data as JSON: /api/errors/11d5e31c8b041948. Report an issue: GitHub.