cloudflare/cloudflared · error
cannot decode empty certificate
Error message
cannot decode empty certificate
What it means
decodeOriginCert parses a PEM bundle into an OriginCert. When the input byte slice is empty there are no PEM blocks to decode, so the function fails fast with this error rather than returning a useless empty cert.
Source
Thrown at credentials/origin_cert.go:85
if err != nil {
return nil, fmt.Errorf("originCert marshal failed: %v", err)
}
block := pem.Block{
Type: "ARGO TUNNEL TOKEN",
Headers: map[string]string{},
Bytes: buffer,
}
var out bytes.Buffer
err = pem.Encode(&out, &block)
if err != nil {
return nil, fmt.Errorf("pem encoding failed: %v", err)
}
return out.Bytes(), nil
}
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)View on GitHub (pinned to 2253eeeb25)
Solutions
- Check the origin cert file exists and has non-zero size before decoding (os.Stat, size > 0)
- Re-download/regenerate the origin cert from Cloudflare (cloudflared tunnel login)
- Verify the --origincert flag points to the correct file, not a placeholder
Example fix
// before
cert, _ := credentials.DecodeOriginCert(blocks)
// after
if len(blocks) == 0 {
return fmt.Errorf("origin cert file is empty; re-run 'cloudflared tunnel login'")
}
cert, err := credentials.DecodeOriginCert(blocks) Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(certPath)
if err != nil || fi.Size() == 0 {
return fmt.Errorf("origin cert %s missing or empty", certPath)
} Type guard
func hasCertData(blocks []byte) bool { return len(blocks) > 0 } Try / catch
cert, err := credentials.DecodeOriginCert(blocks)
if err != nil && strings.Contains(err.Error(), "cannot decode empty certificate") {
// prompt re-login / regenerate cert
} Prevention
- Check file size > 0 before decoding
- Atomic-write credential files (temp + rename) so they are never partially empty
- Alert on empty cert files in deploy pipelines
When it happens
Trigger: Calling credentials/origin_cert.go decodeOriginCert (directly or via Read/DecodeOriginCert) with a nil or zero-length []byte, e.g. after readOriginCert returned empty content.
Common situations: Tunnel credentials file at --origincert path is empty or truncated (disk full during write, mount issue, download interrupted); user points at a zero-byte file.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- pem encoding failed: %v
- found multiple tokens in the certificate
- unknown block %s in the certificate
- missing token in the certificate
- parse CA certificate %s
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/aa9682a9c530843e.
Report an issue: GitHub.