cloudflare/cloudflared · error

originCert marshal failed: %v

Error message

originCert marshal failed: %v

What it means

EncodeOriginCert marshals the certificate struct to JSON before wrapping it in a PEM block. If json.Marshal fails, the error is wrapped as "originCert marshal failed: %v". In practice json.Marshal on this fixed struct rarely fails, but the guard catches unsupported field values or custom marshaler errors, preventing a corrupted PEM token from being produced.

Source

Thrown at credentials/origin_cert.go:68

		originCertPath, _ := homedir.Expand(filepath.Join(defaultConfigDir, DefaultCredentialFile))
		if ok := fileExists(originCertPath); ok {
			return originCertPath
		}
	}
	return ""
}

func DecodeOriginCert(blocks []byte) (*OriginCert, error) {
	return decodeOriginCert(blocks)
}

func (cert *OriginCert) EncodeOriginCert() ([]byte, error) {
	if cert == nil {
		return nil, fmt.Errorf("originCert cannot be nil")
	}
	buffer, err := json.Marshal(cert)
	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")
	}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Inspect the wrapped error to identify which field fails to marshal
  2. Ensure OriginCert fields are plain strings populated from valid decoded data
  3. Rebuild the cert by decoding from the original cert bytes rather than reusing mutated state
  4. If fields come from external input, sanitize/validate strings before assigning them

Example fix

// before
oc.APIToken = string(someBytes) // may contain invalid UTF-8
// after
if !utf8.Valid(someBytes) { return errors.New("apiToken contains invalid UTF-8") }
oc.APIToken = string(someBytes)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure cert fields are plain strings before encoding
for _, s := range []string{cert.APIToken, cert.ZoneID, cert.AccountID} {
	if !utf8.ValidString(s) {
		return errors.New("cert field contains invalid UTF-8 and cannot be marshaled")
	}
}

Try / catch

buffer, err := cert.EncodeOriginCert()
if err != nil {
	if strings.Contains(err.Error(), "originCert marshal failed") {
		// rebuild the cert from raw decoded bytes instead of reusing mutated state
	}
	return err
}

Prevention

When it happens

Trigger: json.Marshal on the OriginCert fails — e.g. a field containing a value that cannot be marshaled (channel, func, or an invalid UTF-8-producing custom marshaler) injected into the struct's fields.

Common situations: Programmatically constructed OriginCert values containing unmarshalable types; custom JSONMarshaler implementations panicking or erroring; corrupt in-memory cert state after partial deserialization.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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