larksuite/cli · error
no part with cid %q found
Error message
no part with cid %q found
What it means
resolveTarget translates an inline-target's cid into a part_id by searching the MIME tree with findPartByCID; when no part carries a matching Content-ID, it returns this error. CIDs are matched after trimming surrounding angle brackets, but the cid must otherwise correspond to an existing inline part in the current draft body.
Source
Thrown at shortcuts/mail/draft/patch.go:799
if removePart(child, targetPartID) {
parent.Dirty = true
return true
}
}
return false
}
// resolveTarget resolves an AttachmentTarget to a concrete part_id.
// Priority: part_id > cid.
func resolveTarget(snapshot *DraftSnapshot, target AttachmentTarget) (string, error) {
if id := strings.TrimSpace(target.PartID); id != "" {
return id, nil
}
if cid := strings.TrimSpace(target.CID); cid != "" {
cid = strings.Trim(cid, "<>")
part := findPartByCID(snapshot.Body, cid)
if part == nil {
return "", fmt.Errorf("no part with cid %q found", cid)
}
return part.PartID, nil
}
return "", fmt.Errorf("target must specify at least one of part_id or cid")
}
func findPartByCID(root *Part, cid string) *Part {
if root == nil {
return nil
}
if strings.EqualFold(strings.Trim(root.ContentID, "<>"), cid) {
return root
}
for _, child := range root.Children {
if found := findPartByCID(child, cid); found != nil {
return found
}
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Re-read the draft and use a cid that currently exists in the MIME tree (or target by part_id instead)
- Strip angle brackets and whitespace and match cid exactly as stored
- If the part was removed earlier in the same patch, drop this op
- Verify the draft you are patching is the same one the cid came from
Example fix
// before
{"op":"remove_inline","target":{"cid":"stale-cid@old-draft"}}
// after — refresh snapshot first
{"op":"remove_inline","target":{"cid":"image001@current-draft"}} Defensive patterns
Strategy: validation
Validate before calling
func cidExists(snap *DraftSnapshot, cid string) bool {
return findPartByCID(snap.Body, strings.Trim(strings.TrimSpace(cid), "<>")) != nil
} Type guard
func partHasCID(p *Part, cid string) bool {
return p != nil && strings.Trim(p.ContentID, "<>") == strings.Trim(cid, "<>")
} Try / catch
if err := applyOp(snap, op); err != nil && strings.Contains(err.Error(), "no part with cid") {
// refresh snapshot, re-list cids, then rebuild the op
} Prevention
- Re-fetch the draft and enumerate existing cids before referencing one
- Normalize cids: trim whitespace and angle brackets, match case exactly
- Drop ops for parts already removed earlier in the same patch
- Prefer part_id when you have it; cid lookup only when the ID is unknown
When it happens
Trigger: Calling an inline patch op (e.g. remove_inline/replace_inline) with target.cid that does not match any part's Content-ID — wrong cid, cid from a different draft, or the inline part was already removed/rewritten in an earlier op.
Common situations: Citing the cid from the original source HTML after the draft's inline parts were regenerated; case/angle-bracket or whitespace mismatches; referencing cid from a previous draft version.
Related errors
- attachment part %q not found
- inline cid is empty
- inline cid %q contains invalid characters (spaces, tabs, ang
- add_inline requires cid
- MIME nesting too deep (max %d levels)
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/cf10dde91141e224.
Report an issue: GitHub.