{"record":{"id":"eda8b584b7abfc1e","repo":"larksuite/cli","slug":"body-kind-must-be-text-plain-or-text-html","errorCode":null,"errorMessage":"body_kind must be text/plain or text/html","messagePattern":"body_kind must be text/plain or text/html","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/model.go","lineNumber":295,"sourceCode":"\t\t\t\treturn fmt.Errorf(\"set_recipients requires non-empty addresses\")\n\t\t\t}\n\t\t}\n\tcase \"add_recipient\", \"remove_recipient\":\n\t\tif !isRecipientField(op.Field) {\n\t\t\treturn fmt.Errorf(\"recipient field must be one of to/cc/bcc\")\n\t\t}\n\t\tif strings.TrimSpace(op.Address) == \"\" {\n\t\t\treturn fmt.Errorf(\"%s requires address\", op.Op)\n\t\t}\n\tcase \"set_reply_to\":\n\t\tif len(op.Addresses) == 0 {\n\t\t\treturn fmt.Errorf(\"set_reply_to requires addresses\")\n\t\t}\n\tcase \"clear_reply_to\":\n\tcase \"set_body\", \"set_reply_body\":\n\tcase \"replace_body\", \"append_body\":\n\t\tif !isBodyKind(op.BodyKind) {\n\t\t\treturn fmt.Errorf(\"body_kind must be text/plain or text/html\")\n\t\t}\n\t\tif op.Selector != \"\" && op.Selector != \"primary\" {\n\t\t\treturn fmt.Errorf(\"selector must be primary\")\n\t\t}\n\tcase \"set_header\":\n\t\tif strings.TrimSpace(op.Name) == \"\" {\n\t\t\treturn fmt.Errorf(\"set_header requires name\")\n\t\t}\n\t\tif strings.ContainsAny(op.Name, \":\\r\\n\") {\n\t\t\treturn fmt.Errorf(\"set_header: header name must not contain ':', CR, or LF\")\n\t\t}\n\t\tif strings.ContainsAny(op.Value, \"\\r\\n\") {\n\t\t\treturn fmt.Errorf(\"set_header: header value must not contain CR or LF\")\n\t\t}\n\tcase \"remove_header\":\n\t\tif strings.TrimSpace(op.Name) == \"\" {\n\t\t\treturn fmt.Errorf(\"remove_header requires name\")\n\t\t}","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/model.go#L277-L313","documentation":"Thrown by PatchOp.Validate() in shortcuts/mail/draft/model.go:295 when replace_body or append_body ops carry a body_kind that is not exactly \"text/plain\" or \"text/html\". isBodyKind(op.BodyKind) enforces the whitelist, including rejecting an empty body_kind. This tells the patch layer which MIME part to operate on.","triggerScenarios":"Ops like {\"op\":\"replace_body\",\"body_kind\":\"html\"}, body_kind:\"text\", body_kind:\"plain\", or body_kind omitted entirely; values with different casing (\"text/HTML\"); an empty string after template substitution.","commonSituations":"Assuming shorthand values (\"html\", \"text\") are accepted; case-sensitivity slips; forgetting body_kind is required for replace/append (unlike set_body/set_reply_body which have no kind constraint); building ops from user config with free-form kind strings.","solutions":["Set body_kind to exactly \"text/plain\" or \"text/html\".","Normalize user/config input before constructing the op: map \"html\"->\"text/html\", \"text\"->\"text/plain\", lower-case the string.","Check the wrapped op index (invalid patch op #N) to find the offending op."],"exampleFix":"// before\n{\"op\":\"replace_body\",\"body_kind\":\"html\",\"value\":\"<p>hi</p>\"}\n\n// after\n{\"op\":\"replace_body\",\"body_kind\":\"text/html\",\"value\":\"<p>hi</p>\"}","handlingStrategy":"validation","validationCode":"func normalizeBodyKind(k string) (string, error) {\n    switch strings.ToLower(strings.TrimSpace(k)) {\n    case \"text/plain\", \"plain\", \"text\": return \"text/plain\", nil\n    case \"text/html\", \"html\": return \"text/html\", nil\n    }\n    return \"\", fmt.Errorf(\"body_kind must be text/plain or text/html\")\n}","typeGuard":"func isBodyKind(k string) bool {\n    return k == \"text/plain\" || k == \"text/html\"\n}","tryCatchPattern":null,"preventionTips":["Use string constants for body kinds instead of inline literals.","Normalize shorthand (\"html\", \"text\") and casing before constructing the op.","Remember body_kind is required for replace_body/append_body even though set_body omits it."],"tags":["mail","validation","patch-op","body"],"backgroundTag":"invalid-enum-value","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}