{"record":{"id":"82800c1c051bb595","repo":"larksuite/cli","slug":"insert-signature-no-html-body-part-found-use-set","errorCode":null,"errorMessage":"insert_signature: no HTML body part found; use set_body first","messagePattern":"insert_signature: no HTML body part found; use set_body first","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":1227,"sourceCode":"\t}\n\tremoveOrphanedInlineParts(snapshot.Body, refSet)\n\treturn nil\n}\n\n// ── Signature patch operations ──\n\n// insertSignatureOp inserts a pre-rendered signature into the HTML body.\n// The RenderedSignatureHTML and SignatureImages fields must be populated\n// by the shortcut layer before calling Apply.\n//\n// Placement: signature goes between the user-authored region and any\n// system-managed tail (large attachment card or history quote wrapper),\n// matching the compose-time order [user][sig][card?][quote?]. When the\n// draft already has a signature, it is replaced in place.\nfunc insertSignatureOp(snapshot *DraftSnapshot, op PatchOp) error {\n\thtmlPart := findPart(snapshot.Body, snapshot.PrimaryHTMLPartID)\n\tif htmlPart == nil {\n\t\treturn fmt.Errorf(\"insert_signature: no HTML body part found; use set_body first\")\n\t}\n\toldHTML := string(htmlPart.Body)\n\n\t// Collect CIDs from old signature before replacement so we can prune\n\t// MIME inline parts that the new signature doesn't re-reference.\n\toldSigCIDs := collectSignatureCIDsFromHTML(oldHTML)\n\n\tsigBlock := SignatureSpacing() + BuildSignatureHTML(op.SignatureID, op.RenderedSignatureHTML)\n\tnewHTML := PlaceSignatureBeforeSystemTail(oldHTML, sigBlock)\n\n\t// Remove orphaned MIME inline parts from old signature.\n\tfor _, cid := range oldSigCIDs {\n\t\tif !containsCIDIgnoreCase(newHTML, cid) {\n\t\t\tremoveMIMEPartByCID(snapshot.Body, cid)\n\t\t}\n\t}\n\n\thtmlPart.Body = []byte(newHTML)","sourceCodeStart":1209,"sourceCodeEnd":1245,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L1209-L1245","documentation":"insertSignatureOp needs an HTML body part in the draft snapshot to splice the signature markup into. If findPart cannot locate the primary HTML part (no multipart/alternative HTML node exists), there is nothing to insert into, so it fails with this directive-style error telling the caller to create a body first. The signature machinery never fabricates an HTML part by itself.","triggerScenarios":"Applying an insert_signature patch op to a snapshot whose Body has no HTML part and whose PrimaryHTMLPartID is empty/unresolvable — typically a plain-text-only draft, or a draft built without a prior set_body that established the HTML part.","commonSituations":"Composing a plain-text mail draft and then trying to add a signature; running signature ops in the wrong order on a freshly created draft; migrating drafts where the HTML alternative part was stripped.","solutions":["Call set_body first so the snapshot gains an HTML body part, then re-run insert_signature","Verify PrimaryHTMLPartID points to the intended HTML part (leave empty only when exactly one HTML part exists)","Inspect the snapshot's parts to confirm a text/html part exists before applying signature ops"],"exampleFix":"// before\napplyOp(snapshot, PatchOp{Type: \"insert_signature\"}) // fails: no HTML part\n// after\nsetBody(snapshot, \"<html><body>Hello</body></html>\") // establishes HTML part\napplyOp(snapshot, PatchOp{Type: \"insert_signature\"})","handlingStrategy":"validation","validationCode":"if findPart(snapshot.Body, snapshot.PrimaryHTMLPartID) == nil {\n  return fmt.Errorf(\"draft has no HTML body; call set_body before insert_signature\")\n}","typeGuard":"func hasHTMLPart(s *DraftSnapshot) bool {\n  return s != nil && findPart(s.Body, s.PrimaryHTMLPartID) != nil\n}","tryCatchPattern":"err := applyOp(snapshot, op)\nif err != nil && strings.Contains(err.Error(), \"no HTML body part found\") {\n  return fmt.Errorf(\"create the draft body first: %w\", err)\n}","preventionTips":["Always run set_body before signature ops","Check the draft has a text/html part for HTML signatures","Keep the op order fixed: set_body → insert_signature → other ops","Assert snapshot invariants in your pipeline before applying ops"],"tags":["mail","draft-patch","signature","precondition"],"backgroundTag":"missing-html-body-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"}