{"record":{"id":"342ebef90bc40edd","repo":"larksuite/cli","slug":"inline-cid-is-empty","errorCode":null,"errorMessage":"inline cid is empty","messagePattern":"inline cid is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":855,"sourceCode":"}\n\n// normalizeCID strips a single RFC 2392 angle-bracket wrapper (<...>) from the\n// CID if present, and trims surrounding whitespace.  Unlike strings.Trim, it\n// only removes a matched pair so that stray brackets like \"test<>\" are preserved\n// for validation to reject.\nfunc normalizeCID(cid string) string {\n\tcid = strings.TrimSpace(cid)\n\tif strings.HasPrefix(cid, \"<\") && strings.HasSuffix(cid, \">\") {\n\t\tcid = cid[1 : len(cid)-1]\n\t}\n\treturn cid\n}\n\n// validateCID checks that a Content-ID value is non-empty and free of\n// characters that would break MIME headers or cause ambiguous references.\nfunc validateCID(cid string) error {\n\tif cid == \"\" {\n\t\treturn fmt.Errorf(\"inline cid is empty\")\n\t}\n\tif err := validate.RejectCRLF(cid, \"inline cid\"); err != nil {\n\t\treturn err\n\t}\n\tif strings.ContainsAny(cid, \" \\t<>()\") {\n\t\treturn fmt.Errorf(\"inline cid %q contains invalid characters (spaces, tabs, angle brackets, or parentheses are not allowed)\", cid)\n\t}\n\treturn nil\n}\n\nfunc ensureInlineContainerRef(partRef **Part) (*Part, error) {\n\tif partRef == nil || *partRef == nil {\n\t\treturn nil, fmt.Errorf(\"body container is nil\")\n\t}\n\tpart := *partRef\n\tif strings.EqualFold(part.MediaType, \"multipart/related\") {\n\t\treturn part, nil\n\t}","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L837-L873","documentation":"validateCID enforces that a Content-ID for an inline part is non-empty before it is used in MIME headers and HTML references. An empty cid would produce an invalid Content-ID header and an unreferenceable <img src=\"cid:...\">, so newInlinePart/replaceInline reject it up front.","triggerScenarios":"Calling inline-add/replace flows with cid:\"\" or whitespace that trims to empty; building the cid programmatically from a variable that was never set.","commonSituations":"Template-driven patch generation with unfilled placeholders; passing the filename instead of a generated cid by mistake; upstream cid extraction returning empty for images without a cid.","solutions":["Supply a non-empty cid, or omit cid and let generateCID create a UUID-based one","Check your cid-producing code for empty results before building the op","Generate the cid from the image path/UUID at call time rather than a blank template"],"exampleFix":"// before\n{\"op\":\"add_inline\",\"target\":{\"cid\":\"\"},\"path\":\"img.png\"}\n// after\n{\"op\":\"add_inline\",\"target\":{\"cid\":\"a1b2c3d4-uuid\"},\"path\":\"img.png\"}","handlingStrategy":"validation","validationCode":"func cidReady(cid string) bool {\n\treturn strings.TrimSpace(cid) != \"\"\n}\n// if empty, omit cid and let generateCID assign a UUID","typeGuard":"func cidReady(cid string) bool {\n\treturn strings.TrimSpace(cid) != \"\"\n}","tryCatchPattern":"if err := applyOp(snap, op); err != nil && strings.Contains(err.Error(), \"inline cid is empty\") {\n\t// regenerate a cid (UUID) and rebuild the op\n}","preventionTips":["Check for empty cid before building the op; auto-generate one if absent","Don't pass placeholders from templates unfilled","Extract cids from source with a fallback to UUID generation"],"tags":["mail","draft","mime","cid","validation","empty-value"],"backgroundTag":"invalid-cid","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"}