{"record":{"id":"d444ac6523378d5b","repo":"multica-ai/multica","slug":"resolve-executable-path-w-d444ac","errorCode":null,"errorMessage":"resolve executable path: %w","messagePattern":"resolve executable path: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":375,"sourceCode":"\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"HTTP %d from %s\", resp.StatusCode, url)\n\t}\n\treturn io.ReadAll(resp.Body)\n}\n\n// UpdateViaDownload downloads the latest release binary from GitHub and replaces\n// the current executable in-place. Returns the combined output message and any error.\nfunc UpdateViaDownload(targetVersion string) (string, error) {\n\treturn UpdateViaDownloadWithTimeout(targetVersion, DefaultUpdateDownloadTimeout)\n}\n\n// UpdateViaDownloadWithTimeout downloads the latest release binary with a caller-selected timeout.\nfunc UpdateViaDownloadWithTimeout(targetVersion string, downloadTimeout time.Duration) (string, error) {\n\t// Determine current binary path.\n\texePath, err := selfexec.Resolve()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"resolve executable path: %w\", err)\n\t}\n\texePath, err = filepath.EvalSymlinks(exePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"resolve symlink: %w\", err)\n\t}\n\n\ttag := normalizeReleaseTag(targetVersion)\n\trelease, err := fetchReleaseByTag(tag)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"fetch release metadata: %w\", err)\n\t}\n\tasset, err := findReleaseAsset(release.Assets, tag, runtime.GOOS, runtime.GOARCH)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tmanifestAsset, err := findChecksumManifestAsset(release.Assets)\n\tif err != nil {\n\t\treturn \"\", err","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L357-L393","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the binary from a stable, on-disk path instead of a temp/piped executable.","If in a container, ensure /proc is mounted so os.Executable works.","Redeploy via your package manager instead of in-place self-update in immutable/container environments.","Check the wrapped error's message — it distinguishes a resolve failure from later stages (symlink, fetch, replace)."],"exampleFix":"null","handlingStrategy":"validation","validationCode":"if _, err := selfexec.Resolve(); err != nil {\n    // skip in-place self-update; require external redeploy\n}","typeGuard":null,"tryCatchPattern":"out, err := cli.UpdateViaDownloadWithTimeout(ver, timeout)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"resolve executable path\") {\n        // environment cannot self-update; fall back to package-manager deploy\n    }\n}","preventionTips":["Run the binary from a stable on-disk path, not a temp or piped executable","Mount /proc in containers so os.Executable works","Prefer external deployment tooling in immutable environments"],"tags":["filesystem","self-update","executable"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}