larksuite/cli · error

remove_signature: no HTML body part found

Error message

remove_signature: no HTML body part found

What it means

removeSignatureOp locates the primary HTML part before attempting signature removal. If the snapshot has no HTML body part at all, there is no signature to remove and no place to look, so it fails with this error, distinct from the 'no signature found' error that fires only when the HTML exists but lacks a signature wrapper.

Source

Thrown at shortcuts/mail/draft/patch.go:1261

	}

	htmlPart.Body = []byte(newHTML)
	htmlPart.Dirty = true

	// Add new signature inline images to the MIME tree.
	for _, img := range op.SignatureImages {
		addInlinePartToSnapshot(snapshot, img.Data, img.ContentType, img.FileName, img.CID)
	}

	syncTextPartFromHTML(snapshot, newHTML)
	return nil
}

// removeSignatureOp removes the signature block from the HTML body.
func removeSignatureOp(snapshot *DraftSnapshot) error {
	htmlPart := findPart(snapshot.Body, snapshot.PrimaryHTMLPartID)
	if htmlPart == nil {
		return fmt.Errorf("remove_signature: no HTML body part found")
	}
	html := string(htmlPart.Body)

	if !signatureWrapperRe.MatchString(html) {
		return fmt.Errorf("no signature found in draft body")
	}

	// Collect CIDs referenced by the signature before removing it.
	sigCIDs := collectSignatureCIDsFromHTML(html)

	// Remove signature and preceding spacing.
	html = RemoveSignatureHTML(html)

	// Remove orphaned inline parts (only if the CID is no longer referenced in remaining HTML).
	for _, cid := range sigCIDs {
		if !containsCIDIgnoreCase(html, cid) {
			removeMIMEPartByCID(snapshot.Body, cid)
		}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Ensure the draft has an HTML body part (set_body) before remove_signature
  2. Skip the remove_signature op when the draft has no HTML part (nothing to remove)
  3. Check PrimaryHTMLPartID correctness if parts exist but are not being found

Example fix

// before
applyOp(snapshot, PatchOp{Type: "remove_signature"}) // plain-text draft
// after
if findPart(snapshot.Body, snapshot.PrimaryHTMLPartID) != nil {
  applyOp(snapshot, PatchOp{Type: "remove_signature"})
}
Defensive patterns

Strategy: type-guard

Type guard

func canRemoveSignature(s *DraftSnapshot) bool {
  return s != nil && findPart(s.Body, s.PrimaryHTMLPartID) != nil
}

Try / catch

err := applyOp(snapshot, op)
if err != nil && strings.Contains(err.Error(), "remove_signature: no HTML body part found") {
  return nil // nothing to remove; treat as no-op
}

Prevention

When it happens

Trigger: Applying a remove_signature op to a snapshot whose Body has no HTML part (no set_body ever ran, or the draft is plain-text-only) so findPart returns nil.

Common situations: Trying to remove a signature from a plain-text-only draft; a snapshot built by a different path that never produced an HTML alternative; misordered patch pipeline where set_body was skipped.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/4e69c2e554929a29. Report an issue: GitHub.