{"record":{"id":"12785531f15d8805","repo":"larksuite/cli","slug":"no-signature-found-in-draft-body","errorCode":null,"errorMessage":"no signature found in draft body","messagePattern":"no signature found in draft body","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":1266,"sourceCode":"\t// Add new signature inline images to the MIME tree.\n\tfor _, img := range op.SignatureImages {\n\t\taddInlinePartToSnapshot(snapshot, img.Data, img.ContentType, img.FileName, img.CID)\n\t}\n\n\tsyncTextPartFromHTML(snapshot, newHTML)\n\treturn nil\n}\n\n// removeSignatureOp removes the signature block from the HTML body.\nfunc removeSignatureOp(snapshot *DraftSnapshot) error {\n\thtmlPart := findPart(snapshot.Body, snapshot.PrimaryHTMLPartID)\n\tif htmlPart == nil {\n\t\treturn fmt.Errorf(\"remove_signature: no HTML body part found\")\n\t}\n\thtml := string(htmlPart.Body)\n\n\tif !signatureWrapperRe.MatchString(html) {\n\t\treturn fmt.Errorf(\"no signature found in draft body\")\n\t}\n\n\t// Collect CIDs referenced by the signature before removing it.\n\tsigCIDs := collectSignatureCIDsFromHTML(html)\n\n\t// Remove signature and preceding spacing.\n\thtml = RemoveSignatureHTML(html)\n\n\t// Remove orphaned inline parts (only if the CID is no longer referenced in remaining HTML).\n\tfor _, cid := range sigCIDs {\n\t\tif !containsCIDIgnoreCase(html, cid) {\n\t\t\tremoveMIMEPartByCID(snapshot.Body, cid)\n\t\t}\n\t}\n\n\thtmlPart.Body = []byte(html)\n\thtmlPart.Dirty = true\n","sourceCodeStart":1248,"sourceCodeEnd":1284,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L1248-L1284","documentation":"After locating the HTML part, removeSignatureOp requires the body to contain the recognizable signature wrapper matched by signatureWrapperRe (the system-managed wrapper markup). If no wrapper is present, there is no signature block to excise, so the op fails rather than silently rewriting the HTML. This is the 'HTML exists but no signature' case.","triggerScenarios":"Applying remove_signature to a draft whose HTML body has no signature wrapper — the draft never had a signature inserted via insert_signature, or the signature markup was manually edited/removed so the regex no longer matches.","commonSituations":"Removing a signature twice (already removed); hand-edited HTML that dropped wrapper classes/IDs the regex depends on; a signature added by another client with different markup.","solutions":["Only call remove_signature when insert_signature previously ran on this draft","Re-insert a signature via insert_signature if you need the canonical wrapper restored","If the signature was hand-written, remove it by editing the HTML instead of via this op"],"exampleFix":"// before\napplyOp(snapshot, PatchOp{Type: \"remove_signature\"}) // second time\n// after\nif signatureWrapperRe.MatchString(string(htmlPart.Body)) {\n  applyOp(snapshot, PatchOp{Type: \"remove_signature\"})\n}","handlingStrategy":"validation","validationCode":"if !signatureWrapperRe.MatchString(htmlPart.Body) {\n  return nil // no signature present; skip removal\n}","typeGuard":"func hasSignature(s *DraftSnapshot) bool {\n  p := findPart(s.Body, s.PrimaryHTMLPartID)\n  return p != nil && signatureWrapperRe.MatchString(p.Body)\n}","tryCatchPattern":"err := applyOp(snapshot, op)\nif err != nil && strings.Contains(err.Error(), \"no signature found in draft body\") {\n  return nil // idempotent: already no signature\n}","preventionTips":["Treat remove_signature as idempotent and guard with the regex first","Do not hand-edit the signature wrapper markup the regex depends on","Only remove signatures that were inserted via insert_signature"],"tags":["mail","draft-patch","signature","not-found"],"backgroundTag":"signature-not-found","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"}