{"record":{"id":"107e366f9fca7ef3","repo":"siyuan-note/siyuan","slug":"marketplace-package-install-path-already-exists","errorCode":null,"errorMessage":"marketplace package install path already exists","messagePattern":"marketplace package install path already exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/install.go","lineNumber":139,"sourceCode":"\t// 文件夹的修改时间设置为当前操作时间\n\tif err = os.Chtimes(installPath, now, now); err != nil {\n\t\tlogging.LogWarnf(\"set package [%s] folder mtime failed: %s\", packageName, err)\n\t}\n\n\tgo incPackageDownloads(repoURL, packageName, systemID)\n\treturn nil\n}\n\nfunc installPackage(data []byte, installPath, pkgType, packageName string, update bool) (err error) {\n\t// 非更新安装时目标目录已存在且非空则拒绝覆盖，防止把其他包的内容写入已有包目录\n\t// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-rpx2-p6hp-x5gj\n\tif !update {\n\t\tcontainsFile, statErr := PackageDirContainsFile(installPath)\n\t\tif statErr != nil && !os.IsNotExist(statErr) {\n\t\t\treturn statErr\n\t\t}\n\t\tif containsFile {\n\t\t\treturn errors.New(\"marketplace package install path already exists\")\n\t\t}\n\t}\n\n\ttmpPackage := filepath.Join(util.TempDir, \"bazaar\", \"package\")\n\tif err = os.MkdirAll(tmpPackage, 0755); err != nil {\n\t\treturn\n\t}\n\tname := gulu.Rand.String(7)\n\ttmp := filepath.Join(tmpPackage, name+\".zip\")\n\tdefer os.RemoveAll(tmp)\n\tif err = os.WriteFile(tmp, data, 0644); err != nil {\n\t\treturn\n\t}\n\n\tunzipPath := filepath.Join(tmpPackage, name)\n\tdefer os.RemoveAll(unzipPath)\n\tif err = gulu.Zip.Unzip(tmp, unzipPath); err != nil {\n\t\tlogging.LogErrorf(\"write file [%s] failed: %s\", installPath, err)","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/bazaar/install.go#L121-L157","documentation":"installPackage refuses a fresh (non-update) install when the target install directory already contains any file. This prevents silently clobbering an existing package directory; overwriting is only allowed through the explicit update path.","triggerScenarios":"Calling InstallPackage (or the kernel install API) for a package whose installPath already has content while update=false.","commonSituations":"Reinstalling a package that is already installed without using the update flag; a leftover/partial directory from a previously failed uninstall; stale state after manually copying files into the package dir.","solutions":["Uninstall the existing package first, then install fresh","Pass update=true (use the marketplace \"update\" flow) to overwrite in place","Inspect the install path for leftovers from an interrupted operation and remove them manually"],"exampleFix":"// before\n// InstallPackage(repoURL, pkgName, pkgType, false /* update */)\n// after\n// UninstallPackage(installPath)\n// InstallPackage(repoURL, pkgName, pkgType, false)","handlingStrategy":"validation","validationCode":"contains, err := bazaar.PackageDirContainsFile(installPath)\nif err == nil && contains {\n    return fmt.Errorf(\"package %s already installed; uninstall or use update\", pkgName)\n}","typeGuard":null,"tryCatchPattern":"if err := InstallPackage(...); err != nil && strings.Contains(err.Error(), \"already exists\") {\n    // either uninstall first or flip update=true and retry\n    UninstallPackage(installPath)\n    err = InstallPackage(...)\n}","preventionTips":["Check installed packages via the marketplace API before installing","Always use the update flow for upgrades, never fresh install over existing dirs","Clean up partial installs after failed operations"],"tags":["filesystem","bazaar","install","conflict"],"backgroundTag":"file-already-exists","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}