{"record":{"id":"af955566e4f3c049","repo":"larksuite/cli","slug":"part-q-is-not-an-inline-mime-part","errorCode":null,"errorMessage":"part %q is not an inline MIME part","messagePattern":"part %q is not an inline MIME part","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":677,"sourceCode":"\t\t}\n\t}\n\tcontainer.Children = append(container.Children, inline)\n\tcontainer.Dirty = true\n\treturn container, nil\n}\n\nfunc addInline(dctx *DraftCtx, snapshot *DraftSnapshot, path, cid, fileName, contentType string) error {\n\t_, err := loadAndAttachInline(dctx, snapshot, path, cid, fileName, nil)\n\treturn err\n}\n\nfunc replaceInline(dctx *DraftCtx, snapshot *DraftSnapshot, partID, path, cid, fileName, contentType 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\tinfo, err := dctx.FIO.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := checkSnapshotAttachmentLimit(snapshot, info.Size(), part); err != nil {\n\t\treturn err\n\t}\n\tf, err := dctx.FIO.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\tcontent, err := io.ReadAll(f)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif strings.TrimSpace(fileName) == \"\" {","sourceCodeStart":659,"sourceCodeEnd":695,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L659-L695","documentation":"Guard in replaceInline: the resolved MIME part exists but is not an inline part (wrong disposition/content type), so it cannot be replaced by an inline image.","triggerScenarios":"applyOp -> replaceInline targeting a regular attachment part or the root part instead of an inline image part.","commonSituations":"Using an attachment partID with the inline-replace flag; draft mixes attachments and inline images and the wrong ID was picked; part was converted between attachment and inline by a previous edit.","solutions":["Re-fetch the draft and pick a partID whose Content-Disposition is inline","Use the regular attachment-replace operation for non-inline parts","If the part should be inline, remove it and re-add it as an inline image"],"exampleFix":"// before\n--replace-inline part_id=att_1   # att_1 is a normal attachment\n// after\n--replace-attachment part_id=att_1 --path ./new.png","handlingStrategy":"type-guard","validationCode":"snap, _ := draftGet(draftID)\np := findPart(snap.Body, partID)\nif p != nil && (p.ContentDisposition != \"inline\") {\n    // route to the attachment-replace operation instead\n}","typeGuard":"func isInline(p *Part) bool {\n    return p != nil && isInlinePart(p)\n}","tryCatchPattern":"if err := replaceInline(...); err != nil {\n    if strings.Contains(err.Error(), \"not an inline MIME part\") {\n        // switch to replace-attachment path\n    }\n}","preventionTips":["Check Content-Disposition of the part before choosing inline vs attachment ops","Keep attachment and inline part IDs in separate collections","Re-fetch after any operation that may reclassify parts"],"tags":["mail","draft","mime-part","content-disposition"],"backgroundTag":"mime-part-not-inline","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"}