{"record":{"id":"6428c916943baf6f","repo":"cloudflare/cloudflared","slug":"origincert-marshal-failed-v","errorCode":null,"errorMessage":"originCert marshal failed: %v","messagePattern":"originCert marshal failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/origin_cert.go","lineNumber":68,"sourceCode":"\t\toriginCertPath, _ := homedir.Expand(filepath.Join(defaultConfigDir, DefaultCredentialFile))\n\t\tif ok := fileExists(originCertPath); ok {\n\t\t\treturn originCertPath\n\t\t}\n\t}\n\treturn \"\"\n}\n\nfunc DecodeOriginCert(blocks []byte) (*OriginCert, error) {\n\treturn decodeOriginCert(blocks)\n}\n\nfunc (cert *OriginCert) EncodeOriginCert() ([]byte, error) {\n\tif cert == nil {\n\t\treturn nil, fmt.Errorf(\"originCert cannot be nil\")\n\t}\n\tbuffer, err := json.Marshal(cert)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"originCert marshal failed: %v\", err)\n\t}\n\tblock := pem.Block{\n\t\tType:    \"ARGO TUNNEL TOKEN\",\n\t\tHeaders: map[string]string{},\n\t\tBytes:   buffer,\n\t}\n\tvar out bytes.Buffer\n\terr = pem.Encode(&out, &block)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"pem encoding failed: %v\", err)\n\t}\n\treturn out.Bytes(), nil\n}\n\nfunc decodeOriginCert(blocks []byte) (*OriginCert, error) {\n\tif len(blocks) == 0 {\n\t\treturn nil, fmt.Errorf(\"cannot decode empty certificate\")\n\t}","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/credentials/origin_cert.go#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"Programmatically constructed OriginCert values containing unmarshalable types; custom JSONMarshaler implementations panicking or erroring; corrupt in-memory cert state after partial deserialization.","solutions":["Inspect the wrapped error to identify which field fails to marshal","Ensure OriginCert fields are plain strings populated from valid decoded data","Rebuild the cert by decoding from the original cert bytes rather than reusing mutated state","If fields come from external input, sanitize/validate strings before assigning them"],"exampleFix":"// before\noc.APIToken = string(someBytes) // may contain invalid UTF-8\n// after\nif !utf8.Valid(someBytes) { return errors.New(\"apiToken contains invalid UTF-8\") }\noc.APIToken = string(someBytes)","handlingStrategy":"try-catch","validationCode":"// ensure cert fields are plain strings before encoding\nfor _, s := range []string{cert.APIToken, cert.ZoneID, cert.AccountID} {\n\tif !utf8.ValidString(s) {\n\t\treturn errors.New(\"cert field contains invalid UTF-8 and cannot be marshaled\")\n\t}\n}","typeGuard":null,"tryCatchPattern":"buffer, err := cert.EncodeOriginCert()\nif err != nil {\n\tif strings.Contains(err.Error(), \"originCert marshal failed\") {\n\t\t// rebuild the cert from raw decoded bytes instead of reusing mutated state\n\t}\n\treturn err\n}","preventionTips":["Populate OriginCert fields only from successfully decoded cert data","Avoid injecting unmarshalable values (channels, funcs) into cert structs","Sanitize external strings (valid UTF-8) before assigning to cert fields"],"tags":["go","json","certificate","marshaling"],"backgroundTag":"json-marshal-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}