siyuan-note/siyuan · error
marketplace package manifest not found or invalid
Error message
marketplace package manifest not found or invalid
What it means
After extraction, installPackage parses the package's manifest (e.g. plugin.json / theme.json per packageManifestNames). If the manifest file is missing, unreadable, or invalid JSON, the install is aborted rather than installing unverified content.
Solutions
- Fix the package archive so the manifest (plugin.json/theme.json/etc.) sits at the archive root and is valid JSON
- Validate the manifest locally (jq / JSON schema check) before publishing
- Re-download the package — the artifact may be truncated; verify archive integrity
- Check that the package type matches the manifest kind actually shipped
Example fix
// before: zip contains my-plugin/dist/... with plugin.json nested in my-plugin/ // after: repackage so plugin.json is at the archive root
Defensive patterns
Strategy: validation
Validate before calling
mf, err := f.ReadFile("plugin.json")
if err != nil { return fmt.Errorf("archive missing plugin.json") }
var pkg PluginJSON
if err := json.Unmarshal(mf, &pkg); err != nil || pkg.Name == "" {
return fmt.Errorf("plugin.json invalid")
} Prevention
- Package archives with the manifest at the archive root
- Validate manifest JSON in CI before publishing a package
- Re-download if the artifact might be truncated
When it happens
Trigger: The downloaded archive does not contain the expected manifest at its root, or the manifest fails ParsePackageJSON (malformed JSON, wrong schema, empty result).
Common situations: Package zip built with an extra top-level folder so the manifest isn't at srcPath root; author released a broken package; truncated/corrupted download; a package type whose archive layout changed across versions.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- invalid marketplace package manifest
- Field [ ] must not be empty
- invalid bazaar index packages
- invalid null bazaar index
- invalid package name
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c325eb2ef7dc0e09.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/bazaar/install.go:179
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 回去。
func replacePackageDirectory(sourcePath, installPath string, update bool) (err error) {
packageInstallLock.Lock()
defer packageInstallLock.Unlock()
View on GitHub (pinned to 9f775e8a12)