xpzouying/xiaohongshu-mcp · error

拷贝 .app: %v: %s

Error message

拷贝 .app: %v: %s

What it means

extractDmg 在 macOS 上把挂载镜像里找到的 .app 拷贝到目标目录时 cp 命令失败:磁盘空间不足、权限不足或目标目录不可写,附带了 cp 的输出便于定位。

Source

Thrown at browser/browser_download.go:327

	if out, err := exec.Command("hdiutil", "attach", archivePath, "-nobrowse", "-mountpoint", mountPoint).CombinedOutput(); err != nil {
		return fmt.Errorf("hdiutil attach: %v: %s", err, out)
	}
	defer exec.Command("hdiutil", "detach", mountPoint, "-quiet").Run()

	var appPath string
	entries, _ := os.ReadDir(mountPoint)
	for _, e := range entries {
		if strings.HasSuffix(e.Name(), ".app") {
			appPath = filepath.Join(mountPoint, e.Name())
			break
		}
	}
	if appPath == "" {
		return fmt.Errorf("dmg 内未找到 .app")
	}
	dstApp := filepath.Join(destDir, filepath.Base(appPath))
	if out, err := exec.Command("cp", "-R", appPath, dstApp).CombinedOutput(); err != nil {
		return fmt.Errorf("拷贝 .app: %v: %s", err, out)
	}
	_ = exec.Command("xattr", "-dr", "com.apple.quarantine", dstApp).Run()
	return nil
}

View on GitHub (pinned to 332d196854)

Solutions

  1. Remove the stale destination bundle at filepath.Join(destDir, appName) and re-run EnsureBrowser
  2. Check free disk space on the destination volume
  3. Verify destDir permissions (must be writable by the current user)
  4. Run `cp -R <mounted>.app <dest>` manually to see the raw failure and confirm the volume is still mounted
  5. Check `hdiutil info` for early detachments; ensure the deferred detach doesn't race the copy

Example fix

// before
if out, err := exec.Command("cp", "-R", appPath, dstApp).CombinedOutput(); err != nil {
	return fmt.Errorf("拷贝 .app: %v: %s", err, out)
}
// after — clear stale destination and retry once
_ = os.RemoveAll(dstApp)
if out, err := exec.Command("cp", "-R", appPath, dstApp).CombinedOutput(); err != nil {
	return fmt.Errorf("拷贝 .app: %v: %s", err, out)
}
Defensive patterns

Strategy: validation

Validate before calling

dstApp := filepath.Join(destDir, appName)
if _, err := os.Stat(dstApp); err == nil {
	// 目标已存在,先清理避免 cp 冲突
	os.RemoveAll(dstApp)
}
if err := unix.Access(destDir, unix.W_OK); err != nil {
	// 目标目录不可写
}

Try / catch

if err := EnsureBrowser(ctx); err != nil {
	if strings.Contains(err.Error(), "拷贝 .app") {
		// 清理目标目录并重试
		os.RemoveAll(destDir)
		return EnsureBrowser(ctx)
	}
	return err
}

Prevention

When it happens

Trigger: extractDmg found appPath and runs exec.Command("cp", "-R", appPath, dstApp).CombinedOutput(); cp exits non-zero (destination exists and is not writable, source vanished after unmount, disk full, permission denied).

Common situations: A previous partial install left a conflicting dstApp directory; the mounted volume detached before the copy finished; the destination directory is read-only or owned by another user; sandboxed/CI environments restrict spawning cp; disk space exhausted mid-copy.

Related errors


AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05). Data as JSON: /api/errors/9d3e7d8520df5c3f. Report an issue: GitHub.