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

  1. Use exactly 'text/plain' or 'text/html' as body_kind
  2. Normalize/validate the kind string against the allowed set before building the op
  3. 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

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


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/a321b7de0c7562fc. Report an issue: GitHub.