multica-ai/multica · error
resolve --attachment path %q: %w
Error message
resolve --attachment path %q: %w
What it means
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).
Source
Thrown at server/cmd/multica/cmd_issue.go:991
func isHTTPURL(path string) bool {
p := strings.TrimSpace(path)
return strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://")
}
// ensureAttachmentWithinWorkdir applies the same workdir containment guard as
// --description-file / --content-file (MUL-4252) to a local --attachment path.
// An agent that writes a chart/report to a machine-shared path like /tmp and
// then attaches it could otherwise pick up another run's — possibly another
// workspace's — stale file (the image version of the /tmp/desc.md leak). URL
// values are filtered by the caller and never reach here. --allow-external-file
// overrides, mirroring the text-flag escape hatch.
func ensureAttachmentWithinWorkdir(cmd *cobra.Command, filePath string) error {
if allow, _ := cmd.Flags().GetBool("allow-external-file"); allow {
return nil
}
within, err := fileWithinWorkingDir(filePath)
if err != nil {
return fmt.Errorf("resolve --attachment path %q: %w", filePath, err)
}
if !within {
return fmt.Errorf(
"--attachment path %q resolves outside the current working directory; "+
"attach files generated inside the task workdir rather than machine-shared "+
"paths like /tmp, where another run's stale file can be attached by mistake. "+
"Pass --allow-external-file to override.",
filePath)
}
return nil
}
// pendingAttachment is a local --attachment file that passed URL filtering and
// the workdir guard and has been read into memory, ready to upload.
type pendingAttachment struct {
path string
data []byte
}View on GitHub (pinned to 2c0912b6ec)
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.
Example fix
# before (dangling artifact symlink) multica issue create --title T --attachment ./latest.png # -> missing target # after ls build/ # confirm the real file multica issue create --title T --attachment ./build/chart-v2.png
Defensive patterns
Strategy: validation
Validate before calling
# attachment must resolve to a real file inside the CWD
p=$(realpath -e "$ATTACH" 2>/dev/null) || { echo "unresolvable attachment: $ATTACH" >&2; exit 1; }
case "$p" in "$(realpath .)"/*) ;; *) echo "attachment outside workdir" >&2; exit 1;; esac Prevention
- Attach real files, not symlinks to build artifacts that may be cleaned up.
- Run realpath -e on attachment paths before invoking the CLI.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- resolve --%s path %q: %w
- --attachment path %q resolves outside the current working di
- read attachment %s: %w
- file not found: %w
- unsupported file format %q: must be .png, .jpg, .jpeg, .gif,
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/bc8668556f3f88a9.
Report an issue: GitHub.