cloudflare/cloudflared · error

unknown block in the certificate

Error message

unknown block %s in the certificate

What it means

Certificate-parsing error in decodeOriginCert: a PEM block in the origin cert file has a type other than 'PRIVATE KEY', 'CERTIFICATE', or 'ARGO TUNNEL TOKEN', i.e. the file contains unexpected material that the loader does not know how to interpret.

Solutions

  1. Inspect the PEM headers in the file and remove blocks with unexpected types
  2. Convert legacy keys to PKCS#8 ('BEGIN PRIVATE KEY') if a key must be bundled
  3. Re-run 'cloudflared tunnel login' to get a pristine cert.pem

Example fix

// before (file contains '-----BEGIN RSA PRIVATE KEY-----')
// after: openssl pkcs8 -topk8 -in key.pem -out key.pkcs8.pem
Defensive patterns

Strategy: validation

Validate before calling

rest := pemBytes
for {
	b, r := pem.Decode(rest)
	if b == nil { break }
	switch b.Type {
	case "PRIVATE KEY", "CERTIFICATE", "ARGO TUNNEL TOKEN":
	default:
		return fmt.Errorf("unsupported PEM block %q", b.Type)
	}
	rest = r
}

Try / catch

cert, err := credentials.DecodeOriginCert(blocks)
if err != nil && strings.HasPrefix(err.Error(), "unknown block") {
	// strip offending block or regenerate cert
}

Prevention

When it happens

Trigger: PEM bundle contains a block whose Type is none of the three allowed, e.g. 'EC PRIVATE KEY', 'RSA PRIVATE KEY', 'ENCRYPTED PRIVATE KEY', or an arbitrary labeled block.

Common situations: User pasted a full openssl-generated key (legacy PEM header) into the origin cert; cert file mixed with unrelated material; editor mangled headers.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/ea087ce4638d5fcf. Report an issue: GitHub.

Appendix: source

Thrown at credentials/origin_cert.go:101

func decodeOriginCert(blocks []byte) (*OriginCert, error) {
	if len(blocks) == 0 {
		return nil, fmt.Errorf("cannot decode empty certificate")
	}
	originCert := OriginCert{}
	block, rest := pem.Decode(blocks)
	for block != nil {
		switch block.Type {
		case "PRIVATE KEY", "CERTIFICATE":
			// this is for legacy purposes.
		case "ARGO TUNNEL TOKEN":
			if originCert.ZoneID != "" || originCert.APIToken != "" {
				return nil, fmt.Errorf("found multiple tokens in the certificate")
			}
			// The token is a string,
			// Try the newer JSON format
			_ = json.Unmarshal(block.Bytes, &originCert)
		default:
			return nil, fmt.Errorf("unknown block %s in the certificate", block.Type)
		}
		block, rest = pem.Decode(rest)
	}

	if originCert.ZoneID == "" || originCert.APIToken == "" {
		return nil, fmt.Errorf("missing token in the certificate")
	}

	return &originCert, nil
}

func readOriginCert(originCertPath string) ([]byte, error) {
	originCert, err := os.ReadFile(originCertPath)
	if err != nil {
		return nil, fmt.Errorf("cannot read %s to load origin certificate", originCertPath)
	}

	return originCert, nil

View on GitHub (pinned to 2253eeeb25)