multica-ai/multica · error

resolve executable path: %w

Error message

resolve executable path: %w

What it means

UpdateViaDownloadWithTimeout starts by resolving the current executable's path via selfexec.Resolve; failure is wrapped as 'resolve executable path: %w'. Without a trustworthy path to the running binary there is nothing to atomically replace, so the update aborts before any network work.

Source

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

	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP %d from %s", resp.StatusCode, url)
	}
	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

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Run the binary from a stable, on-disk path instead of a temp/piped executable.
  2. If in a container, ensure /proc is mounted so os.Executable works.
  3. Redeploy via your package manager instead of in-place self-update in immutable/container environments.
  4. Check the wrapped error's message — it distinguishes a resolve failure from later stages (symlink, fetch, replace).

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

if _, err := selfexec.Resolve(); err != nil {
    // skip in-place self-update; require external redeploy
}

Try / catch

out, err := cli.UpdateViaDownloadWithTimeout(ver, timeout)
if err != nil {
    if strings.HasPrefix(err.Error(), "resolve executable path") {
        // environment cannot self-update; fall back to package-manager deploy
    }
}

Prevention

When it happens

Trigger: os.Executable() fails because /proc is not mounted (some containers, chroots); the binary was started via a deleted file descriptor (exec of an unlinked binary); unusual launch mechanisms (ptrace-injected, some sandbox environments) where argv[0]/proc lookups break.

Common situations: Minimal Docker/scratch containers without /proc; a binary replaced while running and then an update attempted; dev workflows launching a since-rebuilt binary from a temp build directory.

Related errors


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