{"record":{"id":"9089c4d97c39cb51","repo":"larksuite/cli","slug":"add-attachment-requires-path","errorCode":null,"errorMessage":"add_attachment requires path","messagePattern":"add_attachment requires path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/model.go","lineNumber":316,"sourceCode":"\t\t\treturn fmt.Errorf(\"selector must be primary\")\n\t\t}\n\tcase \"set_header\":\n\t\tif strings.TrimSpace(op.Name) == \"\" {\n\t\t\treturn fmt.Errorf(\"set_header requires name\")\n\t\t}\n\t\tif strings.ContainsAny(op.Name, \":\\r\\n\") {\n\t\t\treturn fmt.Errorf(\"set_header: header name must not contain ':', CR, or LF\")\n\t\t}\n\t\tif strings.ContainsAny(op.Value, \"\\r\\n\") {\n\t\t\treturn fmt.Errorf(\"set_header: header value must not contain CR or LF\")\n\t\t}\n\tcase \"remove_header\":\n\t\tif strings.TrimSpace(op.Name) == \"\" {\n\t\t\treturn fmt.Errorf(\"remove_header requires name\")\n\t\t}\n\tcase \"add_attachment\":\n\t\tif strings.TrimSpace(op.Path) == \"\" {\n\t\t\treturn fmt.Errorf(\"add_attachment requires path\")\n\t\t}\n\tcase \"remove_attachment\":\n\t\tif !op.Target.hasAnyKey() {\n\t\t\treturn fmt.Errorf(\"remove_attachment requires target with at least one of part_id, cid, or token\")\n\t\t}\n\tcase \"add_inline\":\n\t\tif strings.TrimSpace(op.Path) == \"\" {\n\t\t\treturn fmt.Errorf(\"add_inline requires path\")\n\t\t}\n\t\tif strings.TrimSpace(op.CID) == \"\" {\n\t\t\treturn fmt.Errorf(\"add_inline requires cid\")\n\t\t}\n\tcase \"replace_inline\":\n\t\tif !op.Target.hasKey() {\n\t\t\treturn fmt.Errorf(\"replace_inline requires target with at least one of part_id or cid\")\n\t\t}\n\t\tif strings.TrimSpace(op.Path) == \"\" {\n\t\t\treturn fmt.Errorf(\"replace_inline requires path\")","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/model.go#L298-L334","documentation":"The mail draft shortcut validates each draft operation before applying it. An `add_attachment` operation without a non-empty `path` field cannot reference any file to upload, so the validator rejects the operation with this error. It is a client-side input validation failure; no API call is made.","triggerScenarios":"Building a draft patch with `{\"op\":\"add_attachment\"}` but omitting `path`, setting it to an empty string, or passing only whitespace (e.g. `\"path\": \"  \"`) — TrimSpace is applied so blank values fail.","commonSituations":"Programmatically generated op lists where the file variable was empty/unset; JSON patches copied from examples of remove_attachment (which uses target instead of path); a script looping over files where one entry lost its path field.","solutions":["Add a non-empty `path` field to the add_attachment operation pointing at the file to attach","Check the source of the path value (env var, glob, config) for an empty or whitespace-only result before building the op","If you only meant to reference an existing attachment, use remove_attachment with a target (part_id/cid/token) instead"],"exampleFix":"// before\n{\"op\":\"add_attachment\"}\n// after\n{\"op\":\"add_attachment\",\"path\":\"/tmp/report.pdf\"}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(op.Path) == \"\" {\n    return fmt.Errorf(\"add_attachment requires path\")\n}","typeGuard":"func hasAddAttachmentPath(op DraftOp) bool { return strings.TrimSpace(op.Path) != \"\" }","tryCatchPattern":null,"preventionTips":["Always populate path when constructing add_attachment ops","Validate op lists with the same TrimSpace check before submitting","Distinguish add_attachment (path) from remove_attachment (target) requirements"],"tags":["validation","mail","draft","missing-field"],"backgroundTag":"missing-required-argument","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"}