{"record":{"id":"cc8c298565f4385f","repo":"larksuite/cli","slug":"cannot-remove-root-mime-part","errorCode":null,"errorMessage":"cannot remove root MIME part","messagePattern":"cannot remove root MIME part","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":742,"sourceCode":"\tpart.ContentDispositionArg = map[string]string{\"filename\": fileName}\n\tpart.ContentID = finalCID\n\tpart.TransferEncoding = \"base64\"\n\tpart.Body = content\n\tpart.Dirty = true\n\tsyncStructuredPartHeaders(part)\n\treturn nil\n}\n\nfunc removeInline(snapshot *DraftSnapshot, partID string) error {\n\tpart := findPart(snapshot.Body, partID)\n\tif part == nil {\n\t\treturn fmt.Errorf(\"inline part %q not found\", partID)\n\t}\n\tif !isInlinePart(part) {\n\t\treturn fmt.Errorf(\"part %q is not an inline MIME part\", partID)\n\t}\n\tif snapshot.Body == nil || snapshot.Body.PartID == partID {\n\t\treturn fmt.Errorf(\"cannot remove root MIME part\")\n\t}\n\tif !removePart(snapshot.Body, partID) {\n\t\treturn fmt.Errorf(\"inline part %q not found\", partID)\n\t}\n\treturn nil\n}\n\nfunc removeAttachment(snapshot *DraftSnapshot, partID string) error {\n\tif snapshot.Body == nil {\n\t\treturn fmt.Errorf(\"draft has no MIME body\")\n\t}\n\tpart := findPart(snapshot.Body, partID)\n\tif part == nil {\n\t\treturn fmt.Errorf(\"attachment part %q not found\", partID)\n\t}\n\tif strings.EqualFold(part.ContentDisposition, \"inline\") || part.ContentID != \"\" {\n\t\treturn fmt.Errorf(\"part %q is an inline MIME part; use remove_inline\", partID)\n\t}","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L724-L760","documentation":"removeInline throws this when the requested partID is the draft body's root MIME part (multipart/mixed or similar). The root container holds all other parts, so deleting it would destroy the message structure and is disallowed.","triggerScenarios":"applyOp -> removeInline where snapshot.Body.PartID == partID (or Body is nil while the ID matches), i.e. the caller passed the root part ID.","commonSituations":"Iterating all part IDs from a draft get and attempting to remove every one, including the root; assuming the root is a removable inline part.","solutions":["Skip the root part ID (compare against the body's own PartID) when iterating parts","Remove only leaf inline parts; the root is managed implicitly","Clear the whole body via the body-level operation instead of removing the root part"],"exampleFix":"// before\nfor id in $(all part ids); do --remove-inline part_id=$id; done\n// after\nfor id in $(leaf inline part ids only); do --remove-inline part_id=$id; done","handlingStrategy":"validation","validationCode":"snap, _ := draftGet(draftID)\nif snap.Body != nil && snap.Body.PartID == partID {\n    return errors.New(\"refusing to remove root MIME part\")\n}","typeGuard":"func isRootPart(snap *DraftSnapshot, id string) bool {\n    return snap != nil && snap.Body != nil && snap.Body.PartID == id\n}","tryCatchPattern":"if err := removeInline(...); err != nil {\n    if strings.Contains(err.Error(), \"cannot remove root MIME part\") {\n        // skip this ID in bulk-removal loops\n    }\n}","preventionTips":["Exclude the body's own PartID from removal candidates","Iterate only leaf parts collected via tree walk","Never treat the root multipart node as a removable part"],"tags":["mail","draft","mime-part","root-part"],"backgroundTag":"cannot-remove-root-mime-part","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"}