multica-ai/multica · error

upload attachment %s: %w

Error message

upload attachment %s: %w

What it means

While adding a comment with attachments, each pre-validated local file is uploaded via client.UploadFile to the issue. This error wraps the failure of one upload (I/O read error, size limit, auth, 5xx) and names the offending file path. Note uploads happen after all files were validated, but a mid-loop failure can still leave earlier attachments orphaned — retrying will re-upload.

Source

Thrown at server/cmd/multica/cmd_issue.go:2000

		return fmt.Errorf("resolve issue: %w", err)
	}
	issueID := issueRef.ID

	// Validate and read ALL attachments before uploading any. URLs are skipped
	// with a warning — `--attachment` only accepts local file paths. Reading
	// everything up front means a later invalid path (external / symlink escape
	// caught by the workdir guard) aborts the call with ZERO uploads, instead
	// of leaving an earlier file uploaded as an orphaned issue attachment while
	// the comment is never posted (which would duplicate on retry — MUL-4252).
	pending, err := collectLocalAttachments(cmd, attachments)
	if err != nil {
		return err
	}
	var attachmentIDs []string
	for _, att := range pending {
		id, uploadErr := client.UploadFile(ctx, att.data, att.path, issueID)
		if uploadErr != nil {
			return fmt.Errorf("upload attachment %s: %w", att.path, uploadErr)
		}
		attachmentIDs = append(attachmentIDs, id)
		fmt.Fprintf(os.Stderr, "Uploaded %s\n", att.path)
	}

	body := map[string]any{"content": content}
	if parentID, _ := cmd.Flags().GetString("parent"); parentID != "" {
		body["parent_id"] = parentID
	}
	if len(attachmentIDs) > 0 {
		body["attachment_ids"] = attachmentIDs
	}
	var result map[string]any
	if err := client.PostJSON(ctx, "/api/issues/"+issueID+"/comments", body, &result); err != nil {
		return fmt.Errorf("add comment: %w", err)
	}

	fmt.Fprintf(os.Stderr, "Comment added to issue %s.\n", issueRef.Display)

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Retry the command once transient network issues clear.
  2. Reduce the attachment size or split it (compress, split archives).
  3. Confirm the file is a regular local file inside the workdir (no symlinks escaping it — the collect step would have caught that earlier).
  4. Check server logs / upload limits if the failure is deterministic.
Defensive patterns

Strategy: retry

Validate before calling

# bash: pre-check every attachment is a readable regular file
for f in "${ATTACHMENTS[@]}"; do
  [[ -f "$f" && -r "$f" ]] || { echo "bad attachment: $f" >&2; exit 2; }
  sz=$(stat -c%s "$f"); [[ $sz -le $MAX_UPLOAD ]] || { echo "$f exceeds $MAX_UPLOAD bytes" >&2; exit 2; }
done

Try / catch

# bash: retry uploads once; report orphans on repeated failure
multica issue comment add "$ISSUE" --content "$BODY" "${ATT[@]/#/--attachment }" || {
  echo "upload failed — earlier files may be orphaned on the issue; check before re-running" >&2; exit 1;
}

Prevention

When it happens

Trigger: `multica issue comment add <issue> --attachment big.bin` where the file exceeds a server size limit, the connection drops mid-upload, or the 60s-extended timeout is still too short for a very large/slow upload.

Common situations: Attaching large binaries over slow links; server-side upload restrictions; flaky networks causing truncated multipart requests.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/f4db327e9e7d9d6f. Report an issue: GitHub.