{"record":{"id":"b946991455ad18d0","repo":"multica-ai/multica","slug":"read-attachment-s-w","errorCode":null,"errorMessage":"read attachment %s: %w","messagePattern":"read attachment (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_issue.go","lineNumber":1031,"sourceCode":"// only accepts local paths). Each remaining path is run through the MUL-4252\n// workdir guard and read into memory; the first invalid or unreadable path\n// returns an error with nothing uploaded. Both `issue create` and\n// `comment add` share this so an invalid attachment can never leave an earlier\n// one uploaded as an orphaned issue attachment while the issue/comment is never\n// created (which would duplicate on retry).\nfunc collectLocalAttachments(cmd *cobra.Command, attachments []string) ([]pendingAttachment, error) {\n\tpending := make([]pendingAttachment, 0, len(attachments))\n\tfor _, filePath := range attachments {\n\t\tif isHTTPURL(filePath) {\n\t\t\tfmt.Fprintf(os.Stderr, \"Skipping --attachment %q: URLs are not supported here, only local file paths.\\n\", filePath)\n\t\t\tcontinue\n\t\t}\n\t\tif err := ensureAttachmentWithinWorkdir(cmd, filePath); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdata, readErr := os.ReadFile(filePath)\n\t\tif readErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"read attachment %s: %w\", filePath, readErr)\n\t\t}\n\t\tpending = append(pending, pendingAttachment{path: filePath, data: data})\n\t}\n\treturn pending, nil\n}\n\nfunc appendUniqueStrings(dst []string, values ...string) []string {\n\tseen := make(map[string]struct{}, len(dst)+len(values))\n\tout := make([]string, 0, len(dst)+len(values))\n\tfor _, v := range append(dst, values...) {\n\t\tv = strings.TrimSpace(v)\n\t\tif v == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif _, ok := seen[v]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseen[v] = struct{}{}","sourceCodeStart":1013,"sourceCodeEnd":1049,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_issue.go#L1013-L1049","documentation":"An --attachment path passed the workdir guard and URL filter, but os.ReadFile then failed. Because the guard only checks path containment (not readability), this typically means the file is unreadable at read time: missing (removed between guard and read), permission denied, or a directory-like path. The %w wraps the OS error, and the message includes the offending path.","triggerScenarios":"Running `multica issue create --attachment <path>` where the file is deleted by a concurrent process in the window between the guard check and ReadFile; mode 0000 or owned by another user; the path is a directory or otherwise not a readable regular file.","commonSituations":"Artifact cleanup jobs racing the attach step; files created root-only then attached by an unprivileged user; paths pointing at directories from templating mistakes.","solutions":["Check the wrapped OS error: ENOENT → file vanished, regenerate it; EACCES → fix ownership/mode (chmod +r) or run as the owning user; EISDIR → point at the actual file.","Verify the file exists and is readable immediately before the command: test -r <path>.","Serialize artifact generation and attachment so cleanup jobs can't race the read.","Regenerate the artifact inside the workdir if it was reaped from a shared location."],"exampleFix":"# before (unreadable artifact)\nmultica issue create --title T --attachment ./chart.png   # mode 0000\n# after\nchmod 644 ./chart.png\nmultica issue create --title T --attachment ./chart.png","handlingStrategy":"validation","validationCode":"# readable, regular, non-empty file before the CLI call\n [ -f \"$ATTACH\" ] && [ -r \"$ATTACH\" ] && [ -s \"$ATTACH\" ] \\\n  || { echo \"attachment missing/unreadable/empty: $ATTACH\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check -f, -r, -s on every attachment path immediately before the command.","Keep artifact generation and attachment in the same script so cleanup jobs can't race the read.","Watch ownership: files created by root must be readable by the invoking user."],"tags":["cli","filesystem","attachments","race-condition"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}