larksuite/cli · error

draft has no primary body container

Error message

draft has no primary body container

What it means

Raised by ensureBodyPart when primaryBodyRootRef cannot return a writable root reference for the body tree — concretely when the snapshot's root pointer is nil (snapshot.Body is nil), so there is no container into which a new primary body part could be created. It guards the rewrite path: even rewrite_entire_draft cannot create a body when the draft has no body container at all.

Source

Thrown at shortcuts/mail/draft/patch.go:436

		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")
	}
	return ensureBodyPartRef(partRef, bodyKind)
}

func primaryBodyRootRef(root **Part) **Part {
	if root == nil || *root == nil {
		return root
	}
	part := *root
	if strings.EqualFold(part.MediaType, "multipart/mixed") {
		for idx := range part.Children {
			child := part.Children[idx]
			if child == nil || strings.EqualFold(child.ContentDisposition, "attachment") {
				continue
			}
			return &part.Children[idx]
		}
		if len(part.Children) == 0 {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Initialize snapshot.Body to a Part (e.g. a text/plain leaf or multipart/mixed container) before invoking the rewrite path.
  2. Create the body via the draft-create flow or set the body on first creation rather than patching an empty snapshot.
  3. If you control snapshot construction, seed the tree with newBodyLeaf(bodyKind) so ensureBodyPartRef can attach/replace it.

Example fix

// before: patching an empty snapshot
err := rewriteBody(snapshot, "text/html", html) // Body == nil
// after: seed the root first
if snapshot.Body == nil {
    snapshot.Body = newBodyLeaf("text/plain")
}
err := rewriteBody(snapshot, "text/html", html)
Defensive patterns

Strategy: validation

Validate before calling

if snapshot.Body == nil {
	snapshot.Body = newBodyLeaf("text/plain") // seed a root before rewriting
}

Type guard

func hasBodyRoot(s *DraftSnapshot) bool { return s != nil && s.Body != nil }

Prevention

When it happens

Trigger: Calling a body rewrite operation (replaceBody with allowRewrite=true) on a snapshot whose Body field is nil — e.g. a draft snapshot with no MIME body, or a snapshot whose only content was never materialized into a Part tree.

Common situations: Patching a freshly created/empty draft whose body tree was never built; snapshots where all body parts were removed leaving Body nil; code paths that deserialize drafts without a root part.

Related errors


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