{"record":{"id":"01cae8c91329bcdc","repo":"multica-ai/multica","slug":"resolve-symlink-w","errorCode":null,"errorMessage":"resolve symlink: %w","messagePattern":"resolve symlink: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":379,"sourceCode":"\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\n\t}\n\tdownloadURL := asset.BrowserDownloadURL\n\tassetName := asset.Name\n","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L361-L397","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check for dangling symlinks in the binary's path: `ls -l $(which multica)` and follow each link manually.","Reinstall the binary at a real path (remove the symlink, place the binary or re-link it to a valid target).","If the symlink is intentional (e.g. version manager), point it at a concrete existing binary before updating.","Retry after fixing — the wrapped fs.PathError names the exact path that failed."],"exampleFix":"null","handlingStrategy":"validation","validationCode":"exe, _ := selfexec.Resolve()\nif real, err := filepath.EvalSymlinks(exe); err != nil {\n    // broken symlink chain: repair install before self-update\n} else {\n    _ = real\n}","typeGuard":null,"tryCatchPattern":"out, err := cli.UpdateViaDownload(ver)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && strings.HasPrefix(err.Error(), \"resolve symlink\") {\n        // reinstall at a real path, then retry\n    }\n}","preventionTips":["Keep symlinks to the binary pointing at existing versioned binaries","Avoid symlink loops or dangling links in install paths","Re-link after uninstalling version managers"],"tags":["filesystem","symlink","self-update"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}