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
- Use a supported package type: plugin, theme, icon, template, widget
- Normalize the type string (case, whitespace) before calling
- 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
- Keep a canonical allowlist of package types shared between frontend and kernel
- Normalize/trim package type strings from API callers
- When adding a new package kind, update kernel and frontend together
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
- ErrInvalidColumnAlign
- Field [mode] must be 0 or 1
- Field [ ] has an invalid value
- Field [ ] must not be empty
- incomplete bazaar index metadata
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)