siyuan-note/siyuan · critical

install local marketplace package failed: %w; rollback faile

Error message

install local marketplace package failed: %w; rollback failed: %s

What it means

Returned by InstallLocalPackage (kernel/bazaar/install.go:215-219) during an update operation (update == true) when the atomic rename of stagingPath to installPath fails AND the subsequent rollback rename of backupPath to installPath also fails. This is a double-failure: the primary install failed and recovery failed too. The preserveOperationPath flag is set to true so the operation directory (containing both staging and backup) is NOT cleaned up by the deferred RemoveAll, leaving it for manual recovery. The error message includes both the primary error (%w) and the rollback error (%s).

Source

Thrown at kernel/bazaar/install.go:219

	defer func() {
		if !preserveOperationPath {
			_ = os.RemoveAll(operationPath)
		}
	}()
	if err = filelock.Copy(sourcePath, stagingPath); err != nil {
		return
	}

	if update {
		if err = os.Rename(installPath, backupPath); err != nil {
			return
		}
	}
	if err = os.Rename(stagingPath, installPath); err != nil {
		if update {
			if rollbackErr := os.Rename(backupPath, installPath); rollbackErr != nil {
				preserveOperationPath = true
				return fmt.Errorf("install local marketplace package failed: %w; rollback failed: %s", err, rollbackErr)
			}
		}
		return
	}
	if update {
		if removeErr := os.RemoveAll(operationPath); removeErr != nil {
			logging.LogWarnf("remove local package backup [%s] failed: %s", backupPath, removeErr)
		}
	}

	RemoveInstalledPackageSizeCache(pkgType, packageName)
	now := time.Now()
	recordPackageOperationTime(pkgType, packageName, now, fallbackInstallTime, update)
	if chtimesErr := os.Chtimes(installPath, now, now); chtimesErr != nil {
		logging.LogWarnf("set package [%s] folder mtime failed: %s", packageName, chtimesErr)
	}
	return
}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Close other applications that may be accessing the package directory (antivirus, file managers, other SiYuan instances)
  2. Check available disk space on the target volume
  3. Inspect the preserved operation directory (.siyuan-package-install-*) — it contains both staging and backup, allowing manual recovery
  4. Check filesystem permissions on the install path and its parent
  5. On Windows, try again after temporarily disabling antivirus real-time scanning for the SiYuan data directory
Defensive patterns

Strategy: try-catch

Validate before calling

func checkInstallPathWritable(installPath string) error {
    parent := filepath.Dir(installPath)
    testFile := filepath.Join(parent, ".siyuan-write-test-"+gulu.Rand.String(7))
    if err := os.WriteFile(testFile, []byte("test"), 0644); err != nil {
        return fmt.Errorf("install directory is not writable: %w", err)
    }
    os.Remove(testFile)
    return nil
}

Try / catch

err := bazaar.InstallLocalPackage(sourcePath, installPath, pkgType, packageName, true)
if err != nil {
    if strings.Contains(err.Error(), "rollback failed") {
        // Critical: the operation directory is preserved at .siyuan-package-install-*
        // Log the path for manual recovery and alert the user
        logging.LogErrorf("install + rollback failed: %v — operation dir preserved for manual recovery", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling InstallLocalPackage with update=true, where the final os.Rename(staging, install) fails (e.g. another process holds a lock on installPath) and the rollback os.Rename(backup, install) also fails.

Common situations: Antivirus or file indexer locking the install directory during rename on Windows; disk full preventing rename; filesystem corruption; another SiYuan instance or process accessing the package directory concurrently; permission issues on the parent directory.

Related errors


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