larksuite/cli · error
unsupported body kind %q
Error message
unsupported body kind %q
What it means
bodyPartForKind maps a body_kind string to the corresponding primary part ID. Only 'text/plain' and 'text/html' are recognized; any other value (including typos like 'text/html;' or 'plain') is rejected with this error before any part lookup.
Source
Thrown at shortcuts/mail/draft/patch.go:418
func coupledBodySetBodyInputError(snapshot *DraftSnapshot, value string) error {
if !hasCoupledBodySummary(snapshot) {
return nil
}
if bodyLooksLikeHTML(value) {
return nil
}
return fmt.Errorf("draft main body is text/html and text/plain is only its summary; set_body requires HTML input for this draft")
}
func bodyPartForKind(snapshot *DraftSnapshot, bodyKind string, allowRewrite bool) (*Part, error) {
var partID string
switch strings.ToLower(bodyKind) {
case "text/plain":
partID = snapshot.PrimaryTextPartID
case "text/html":
partID = snapshot.PrimaryHTMLPartID
default:
return nil, fmt.Errorf("unsupported body kind %q", bodyKind)
}
if partID == "" {
if !allowRewrite {
return nil, fmt.Errorf("draft has no primary %s body part", bodyKind)
}
return ensureBodyPart(snapshot, bodyKind)
}
part := findPart(snapshot.Body, partID)
if part == nil {
return nil, fmt.Errorf("body part %s not found", partID)
}
return part, nil
}
func ensureBodyPart(snapshot *DraftSnapshot, bodyKind string) (*Part, error) {
partRef := primaryBodyRootRef(&snapshot.Body)
if partRef == nil {
return nil, fmt.Errorf("draft has no primary body container")View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Use exactly 'text/plain' or 'text/html' as body_kind
- Normalize/validate the kind string against the allowed set before building the op
- If the kind comes from user input, map unsupported values explicitly instead of passing them through
Example fix
// before
applyOp(Op{Op: "replace_body", BodyKind: "html", Value: html})
// after
applyOp(Op{Op: "replace_body", BodyKind: "text/html", Value: html}) Defensive patterns
Strategy: validation
Validate before calling
var validBodyKinds = map[string]bool{"text/plain": true, "text/html": true}
if !validBodyKinds[strings.ToLower(strings.TrimSpace(kind))] {
return fmt.Errorf("body_kind must be text/plain or text/html")
} Type guard
func isBodyKind(s string) bool {
switch strings.ToLower(strings.TrimSpace(s)) {
case "text/plain", "text/html":
return true
}
return false
} Prevention
- Only pass the literal values 'text/plain' or 'text/html' as body_kind
- Normalize user/config-provided kind strings against the allowed set
- Keep MIME attachment types (application/pdf, etc.) out of body_kind
When it happens
Trigger: A replace_body or append_body patch op (via applyOp) with body_kind not exactly 'text/plain' or 'text/html' (case-insensitive) — e.g. 'html', 'text', 'text/calendar', or a value with trailing whitespace characters.
Common situations: Typos or abbreviated kind names in scripts; passing a MIME type from elsewhere (e.g. attachment content types like application/pdf); config values copied from another tool's API.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- recipient field must be one of to/cc/bcc
- recipient address is empty
- draft main body is text/html and text/plain is only its summ
- set_calendar: event_start must be a valid ISO 8601 timestamp
- set_calendar: event_end must be a valid ISO 8601 timestamp
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/a321b7de0c7562fc.
Report an issue: GitHub.