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
- Initialize snapshot.Body to a Part (e.g. a text/plain leaf or multipart/mixed container) before invoking the rewrite path.
- Create the body via the draft-create flow or set the body on first creation rather than patching an empty snapshot.
- 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
- Seed a body root when constructing snapshots for empty/new drafts.
- Check snapshot.Body for nil before any body rewrite operation.
- Build bodies at draft creation rather than patching empty snapshots.
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
- draft has no primary %s body part
- body part %s not found
- body container is nil
- cannot rewrite non-body media type %q
- rewrite_entire_draft cannot synthesize body inside %q
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/adddb5c2dd751966.
Report an issue: GitHub.