multica-ai/multica · error

mklink /J

Error message

mklink /J %s %s: %s: %w

What it means

Windows-only createDirLink: os.Symlink failed (no Developer Mode / admin), and the cmd mklink /J junction fallback also failed. The error includes mklink's combined output, so the reason (existing destination, invalid path, privilege issue) is in the message text.

Solutions

  1. Read the embedded mklink output — 'Cannot create a file when that file already exists' means the dst must be removed first
  2. Delete the stale junction/directory at dst and retry
  3. Enable Windows Developer Mode so os.Symlink succeeds directly
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Lstat(dst); err == nil {
	return fmt.Errorf("link destination already exists: %s", dst)
}

Try / catch

if err := createDirLink(src, dst); err != nil {
	if strings.Contains(err.Error(), "Already exists") || strings.Contains(err.Error(), "already exists") {
		_ = os.Remove(dst)
		err = createDirLink(src, dst)
	}
}

Prevention

When it happens

Trigger: Exposing the shared plugin cache into a task home where the junction destination already exists; path with characters cmd misparses; mklink unavailable on the Windows edition.

Common situations: Reused task home already containing plugins\cache; leftover junction from a crashed run; Windows Server Core without standard cmd tooling.

Related errors


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

Appendix: source

Thrown at server/internal/daemon/execenv/codex_home_link_windows.go:20

package execenv

import (
	"fmt"
	"os"
	"os/exec"
)

// createDirLink tries os.Symlink first (requires Developer Mode or admin on
// Windows). If that fails, it falls back to a directory junction (mklink /J)
// which works without elevated privileges.
func createDirLink(src, dst string) error {
	if err := os.Symlink(src, dst); err == nil {
		return nil
	}
	out, err := exec.Command("cmd", "/c", "mklink", "/J", dst, src).CombinedOutput()
	if err != nil {
		return fmt.Errorf("mklink /J %s %s: %s: %w", dst, src, out, err)
	}
	return nil
}

// createFileLink tries os.Symlink first. If that fails, it falls back to
// copying the file so the content is still available.
func createFileLink(src, dst string) error {
	if err := os.Symlink(src, dst); err == nil {
		return nil
	}
	return copyFile(src, dst)
}

View on GitHub (pinned to 2c0912b6ec)