{"record":{"id":"bc8668556f3f88a9","repo":"multica-ai/multica","slug":"resolve-attachment-path-q-w","errorCode":null,"errorMessage":"resolve --attachment path %q: %w","messagePattern":"resolve --attachment path %q: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_issue.go","lineNumber":991,"sourceCode":"func isHTTPURL(path string) bool {\n\tp := strings.TrimSpace(path)\n\treturn strings.HasPrefix(p, \"http://\") || strings.HasPrefix(p, \"https://\")\n}\n\n// ensureAttachmentWithinWorkdir applies the same workdir containment guard as\n// --description-file / --content-file (MUL-4252) to a local --attachment path.\n// An agent that writes a chart/report to a machine-shared path like /tmp and\n// then attaches it could otherwise pick up another run's — possibly another\n// workspace's — stale file (the image version of the /tmp/desc.md leak). URL\n// values are filtered by the caller and never reach here. --allow-external-file\n// overrides, mirroring the text-flag escape hatch.\nfunc ensureAttachmentWithinWorkdir(cmd *cobra.Command, filePath string) error {\n\tif allow, _ := cmd.Flags().GetBool(\"allow-external-file\"); allow {\n\t\treturn nil\n\t}\n\twithin, err := fileWithinWorkingDir(filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"resolve --attachment path %q: %w\", filePath, err)\n\t}\n\tif !within {\n\t\treturn fmt.Errorf(\n\t\t\t\"--attachment path %q resolves outside the current working directory; \"+\n\t\t\t\t\"attach files generated inside the task workdir rather than machine-shared \"+\n\t\t\t\t\"paths like /tmp, where another run's stale file can be attached by mistake. \"+\n\t\t\t\t\"Pass --allow-external-file to override.\",\n\t\t\tfilePath)\n\t}\n\treturn nil\n}\n\n// pendingAttachment is a local --attachment file that passed URL filtering and\n// the workdir guard and has been read into memory, ready to upload.\ntype pendingAttachment struct {\n\tpath string\n\tdata []byte\n}","sourceCodeStart":973,"sourceCodeEnd":1009,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_issue.go#L973-L1009","documentation":"While enforcing that a local --attachment path stays within the working directory, the attachment variant of the workdir guard could not resolve the path at all (fileWithinWorkingDir errored). The %w wraps the OS-level cause from resolution — dangling symlink, permission-denied traversal, symlink loop, or similar. URL-valued attachments never reach this code (they're filtered by isHTTPURL earlier).","triggerScenarios":"Running `multica issue create --attachment <path>` where <path> is a broken symlink, sits behind a stale mount, or cannot be stat'd by the resolving user — and --allow-external-file is not set.","commonSituations":"Artifact symlinks (latest.png -> build/output.png) where the target was cleaned up; containerized runs with different mount visibility; CI artifacts copied as dangling symlinks.","solutions":["Read the wrapped OS error for the concrete cause (ENOENT, EACCES, ELOOP).","Resolve the symlink chain (realpath) and attach the real file, placed inside the workdir.","Regenerate the artifact if the target is missing.","If the outside path is intentional, pass --allow-external-file."],"exampleFix":"# before (dangling artifact symlink)\nmultica issue create --title T --attachment ./latest.png   # -> missing target\n# after\nls build/   # confirm the real file\nmultica issue create --title T --attachment ./build/chart-v2.png","handlingStrategy":"validation","validationCode":"# attachment must resolve to a real file inside the CWD\n p=$(realpath -e \"$ATTACH\" 2>/dev/null) || { echo \"unresolvable attachment: $ATTACH\" >&2; exit 1; }\ncase \"$p\" in \"$(realpath .)\"/*) ;; *) echo \"attachment outside workdir\" >&2; exit 1;; esac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Attach real files, not symlinks to build artifacts that may be cleaned up.","Run realpath -e on attachment paths before invoking the CLI."],"tags":["cli","filesystem","symlink","attachments"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}