siyuan-note/siyuan · error

invalid marketplace package type

Error message

invalid marketplace package type

What it means

installPackage maps the requested package type (plugin/theme/icon/template/widget) to its manifest filename via packageManifestNames. An unknown package type has no manifest name, so the install is rejected before any files are extracted.

Solutions

  1. Use a supported package type: plugin, theme, icon, template, widget
  2. Normalize the type string (case, whitespace) before calling
  3. Upgrade the kernel if a new package type was introduced in a newer frontend

Example fix

// before
// installPackage(u, "my-pkg", "Plugin", installPath, false)
// after
// installPackage(u, "my-pkg", "plugin", installPath, false)
Defensive patterns

Strategy: validation

Validate before calling

var validTypes = map[string]bool{"plugin":true,"theme":true,"icon":true,"template":true,"widget":true}
if !validTypes[pkgType] {
    return fmt.Errorf("unsupported package type: %s", pkgType)
}

Prevention

When it happens

Trigger: Calling InstallPackage with a pkgType string that is not one of the recognized marketplace package types.

Common situations: API callers passing a plugin-provided type string verbatim, typos like "plugisn", forward-compatibility issues when a new package kind exists client-side but not in the kernel.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/4a359c657c6c14e5. Report an issue: GitHub.

Appendix: source

Thrown at kernel/bazaar/install.go:175

		logging.LogErrorf("write file [%s] failed: %s", installPath, err)
		return
	}

	dirs, err := os.ReadDir(unzipPath)
	if err != nil {
		return
	}

	srcPath := unzipPath
	if 1 == len(dirs) && dirs[0].IsDir() {
		srcPath = filepath.Join(unzipPath, dirs[0].Name())
	}

	// 校验下载包自身声明的名称与请求安装的包名一致,防止把其他包的内容写入指定目录
	// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-rpx2-p6hp-x5gj
	jsonFileName, ok := packageManifestNames[pkgType]
	if !ok {
		return errors.New("invalid marketplace package type")
	}
	pkg, parseErr := ParsePackageJSON(filepath.Join(srcPath, jsonFileName))
	if parseErr != nil || nil == pkg {
		return errors.New("marketplace package manifest not found or invalid")
	}
	if packageName != pkg.Name {
		return fmt.Errorf("marketplace package name mismatch: expected [%s], got [%s]", packageName, pkg.Name)
	}

	if err = replacePackageDirectory(srcPath, installPath, update); err != nil {
		return
	}
	return
}

// replacePackageDirectory 将 sourcePath 整目录替换到 installPath。
// 先拷到安装目录同级的 staging,更新时再把旧目录 rename 成 backup,最后把 staging rename 成目标路径。
// 这样新包已删除的文件不会残留,失败时也可以把 backup rename 回去。

View on GitHub (pinned to 9f775e8a12)