multica-ai/multica · error

resolve symlink: %w

Error message

resolve symlink: %w

What it means

After resolving the executable, the updater calls filepath.EvalSymlinks to get the real file behind any symlink chain; failure is wrapped as 'resolve symlink: %w'. Symlinks in the path must be resolved so the temp file is created in the same directory as the real binary, which is required for the atomic rename to work (rename does not cross filesystems).

Source

Thrown at server/internal/cli/update.go:379

	return io.ReadAll(resp.Body)
}

// UpdateViaDownload downloads the latest release binary from GitHub and replaces
// the current executable in-place. Returns the combined output message and any error.
func UpdateViaDownload(targetVersion string) (string, error) {
	return UpdateViaDownloadWithTimeout(targetVersion, DefaultUpdateDownloadTimeout)
}

// UpdateViaDownloadWithTimeout downloads the latest release binary with a caller-selected timeout.
func UpdateViaDownloadWithTimeout(targetVersion string, downloadTimeout time.Duration) (string, error) {
	// Determine current binary path.
	exePath, err := selfexec.Resolve()
	if err != nil {
		return "", fmt.Errorf("resolve executable path: %w", err)
	}
	exePath, err = filepath.EvalSymlinks(exePath)
	if err != nil {
		return "", fmt.Errorf("resolve symlink: %w", err)
	}

	tag := normalizeReleaseTag(targetVersion)
	release, err := fetchReleaseByTag(tag)
	if err != nil {
		return "", fmt.Errorf("fetch release metadata: %w", err)
	}
	asset, err := findReleaseAsset(release.Assets, tag, runtime.GOOS, runtime.GOARCH)
	if err != nil {
		return "", err
	}
	manifestAsset, err := findChecksumManifestAsset(release.Assets)
	if err != nil {
		return "", err
	}
	downloadURL := asset.BrowserDownloadURL
	assetName := asset.Name

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Check for dangling symlinks in the binary's path: `ls -l $(which multica)` and follow each link manually.
  2. Reinstall the binary at a real path (remove the symlink, place the binary or re-link it to a valid target).
  3. If the symlink is intentional (e.g. version manager), point it at a concrete existing binary before updating.
  4. Retry after fixing — the wrapped fs.PathError names the exact path that failed.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

exe, _ := selfexec.Resolve()
if real, err := filepath.EvalSymlinks(exe); err != nil {
    // broken symlink chain: repair install before self-update
} else {
    _ = real
}

Try / catch

out, err := cli.UpdateViaDownload(ver)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && strings.HasPrefix(err.Error(), "resolve symlink") {
        // reinstall at a real path, then retry
    }
}

Prevention

When it happens

Trigger: A symlink in the binary's path points to a deleted or dangling target; a symlink loop (a -> b -> a); a path component replaced between the Resolve call and EvalSymlinks; permission to traverse a symlinked directory is missing.

Common situations: Users symlink /usr/local/bin/multica to a versioned binary that was later removed by another package manager; dev setups with symlinked build outputs cleaned by a parallel build.

Related errors


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