siyuan-note/siyuan · error

built-in marketplace package cannot be overwritten

Error message

built-in marketplace package cannot be overwritten

What it means

Thrown by InstallLocalBazaarPackage when installing an uploaded local archive whose package name collides with a built-in theme (daylight or midnight) or built-in icon (litheness). Built-in appearance assets are protected from overwrite because replacing them can break the default UI.

Source

Thrown at kernel/model/bazaar.go:628

// InstallLocalBazaarPackage 安装上传的本地集市包。
func InstallLocalBazaarPackage(archivePath, frontend string, overwrite bool) (result *LocalBazaarPackageInstallResult, err error) {
	pkgType, pkg, sourcePath, cleanup, err := bazaar.ExtractLocalPackage(archivePath)
	if err != nil {
		return nil, err
	}
	defer cleanup()

	result = &LocalBazaarPackageInstallResult{
		PackageType:   pkgType,
		PackageName:   pkg.Name,
		MinAppVersion: pkg.MinAppVersion,
	}
	installPath, _, err := getPackageInstallPath(pkgType, pkg.Name)
	if err != nil {
		return result, err
	}
	if (pkgType == "themes" && isBuiltInTheme(pkg.Name)) || (pkgType == "icons" && isBuiltInIcon(pkg.Name)) {
		return result, errors.New("built-in marketplace package cannot be overwritten")
	}
	if bazaar.IsBelowRequiredAppVersion(pkg) {
		return result, fmt.Errorf("%w: SiYuan %s or later is required", ErrLocalBazaarPackageIncompatible, pkg.MinAppVersion)
	}
	if (pkgType == "plugins" && bazaar.IsIncompatiblePlugin(pkg, frontend)) ||
		(pkgType == "themes" && bazaar.IsIncompatibleTheme(pkg, frontend)) {
		return result, ErrLocalBazaarPackageIncompatible
	}

	localBazaarInstallLock.Lock()
	defer localBazaarInstallLock.Unlock()
	_, statErr := os.Lstat(installPath)
	if statErr != nil && !os.IsNotExist(statErr) {
		return result, statErr
	}
	result.Updated = statErr == nil
	if result.Updated && !overwrite {
		return result, ErrLocalBazaarPackageExists

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Rename the package in its manifest (theme.json/icon.json) and archive to a non-built-in name before installing.
  2. If you genuinely need a custom default, distribute it as a separate package rather than overwriting the built-in.

Example fix

// theme.json
// before
{ "name": "daylight", ... }
// after
{ "name": "my-daylight", ... }
Defensive patterns

Strategy: validation

Validate before calling

// Block built-in names before attempting local install.
if (pkgType == "themes" && (strings.EqualFold(pkg.Name, "daylight") || strings.EqualFold(pkg.Name, "midnight"))) ||
    (pkgType == "icons" && strings.EqualFold(pkg.Name, "litheness")) {
    return fmt.Errorf("cannot overwrite built-in package %q", pkg.Name)
}

Type guard

func isBuiltInPkgName(pkgType, name string) bool {
    switch pkgType {
    case "themes":
        return strings.EqualFold(name, "daylight") || strings.EqualFold(name, "midnight")
    case "icons":
        return strings.EqualFold(name, "litheness")
    }
    return false
}

Prevention

When it happens

Trigger: Uploading and installing a local theme archive whose manifest name is 'daylight' or 'midnight', or a local icon archive whose name is 'litheness'. The check uses case-insensitive comparison (strings.EqualFold), so casing variants are also blocked.

Common situations: A user or packaging tool reused a built-in package name for a custom theme/icon, or tried to 'replace' the default appearance. The guard prevents corrupting the fallback theme/icon.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/6441cad48faf7a4e. Report an issue: GitHub.