siyuan-note/siyuan · warning · ErrLocalBazaarPackageExists
ErrLocalBazaarPackageExists
ErrLocalBazaarPackageExists
Error message
marketplace package already exists
What it means
Sentinel error ErrLocalBazaarPackageExists, returned by InstallLocalBazaarPackage when the target install path already exists (os.Lstat succeeds, so result.Updated is true) but the caller did not pass overwrite=true. It is a soft conflict: the package is present and the user must explicitly choose to replace it.
Source
Thrown at kernel/model/bazaar.go:110
meta installMeta
}
// ThemeInstallOptions 描述新安装主题后需要应用的外观模式
type ThemeInstallOptions struct {
Mode int
ModeOS bool
}
// LocalBazaarPackageInstallResult 描述本地集市包的识别和安装结果。
type LocalBazaarPackageInstallResult struct {
PackageType string `json:"packageType"`
PackageName string `json:"packageName"`
MinAppVersion string `json:"minAppVersion,omitempty"`
Updated bool `json:"updated"`
}
var (
ErrLocalBazaarPackageExists = errors.New("marketplace package already exists")
ErrLocalBazaarPackageIncompatible = errors.New("marketplace package is incompatible")
localBazaarInstallLock sync.Mutex
)
// updatePackages 更新一组集市包;同类型批量更新时,安装后处理只执行一次
func updatePackages(packages []*UpdatedPackage, pkgType string, successCount, failedCount *int, planned int) {
items := make([]batchInstallItem, 0, len(packages))
for _, updated := range packages {
pkg := updated.Available
meta, err := installBazaarPackage(pkgType, pkg.RepoURL, pkg.RepoHash, pkg.Name)
if err != nil {
logging.LogErrorf("update %s [%s] failed: %s", pkgType, pkg.Name, err)
util.PushErrMsg(fmt.Sprintf(Conf.language(238), pkg.Name), 5000)
*failedCount++
continue
}
items = append(items, batchInstallItem{name: pkg.Name, meta: meta})
*successCount++View on GitHub (pinned to 251596fc0d)
Solutions
- If you intend to replace the existing package, retry the install with overwrite=true.
- If you did not expect a duplicate, uninstall the existing package first, then install.
- Check errors.Is(err, model.ErrLocalBazaarPackageExists) to surface a 'replace?' prompt in the UI.
Example fix
// before result, err := model.InstallLocalBazaarPackage(archivePath, frontend, false) // after (if replacement is intended) result, err := model.InstallLocalBazaarPackage(archivePath, frontend, true)
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check existence and decide whether to overwrite.
_, statErr := os.Lstat(installPath)
if statErr == nil && !overwrite {
// surface a 'package already exists, replace?' prompt instead of failing
} Try / catch
result, err := model.InstallLocalBazaarPackage(archivePath, frontend, overwrite)
if err != nil {
if errors.Is(err, model.ErrLocalBazaarPackageExists) {
// prompt user to confirm overwrite, then retry with overwrite=true
result, err = model.InstallLocalBazaarPackage(archivePath, frontend, true)
}
} Prevention
- Check whether the target package directory exists before installing.
- Use errors.Is against the sentinel ErrLocalBazaarPackageExists to drive a replace prompt.
- Make overwrite an explicit user decision in the UI.
When it happens
Trigger: Uploading and installing a local package (archive) whose name already corresponds to an installed package directory, without setting the overwrite flag in the install-local API call.
Common situations: Reinstalling or re-importing a plugin/theme/icon that is already on disk; or a user double-triggering the install. The previous install is intact, so this is recoverable without data loss.
Related errors
- ErrLocalBazaarPackageIncompatible
- invalid package name
- invalid package type
- installed package not found
- Failed to install marketplace package [%s]: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/5bb934be99a0b7f1.
Report an issue: GitHub.