{"record":{"id":"2918669f5a45b6e3","repo":"siyuan-note/siyuan","slug":"marketplace-package-archive-is-empty","errorCode":null,"errorMessage":"marketplace package archive is empty","messagePattern":"marketplace package archive is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/local.go","lineNumber":97,"sourceCode":"\t}\n\n\tpkg, err = ParsePackageJSON(manifestPath)\n\tif err != nil || pkg == nil {\n\t\terr = errors.New(\"invalid marketplace package manifest\")\n\t\tcleanup()\n\t}\n\treturn\n}\n\nfunc extractLocalPackageArchive(archivePath, destination string) error {\n\treader, err := zip.OpenReader(archivePath)\n\tif err != nil {\n\t\treturn errors.New(\"invalid marketplace package archive\")\n\t}\n\tdefer reader.Close()\n\n\tif len(reader.File) == 0 {\n\t\treturn errors.New(\"marketplace package archive is empty\")\n\t}\n\tif len(reader.File) > maxLocalPackageFileCount {\n\t\treturn errors.New(\"marketplace package contains too many files\")\n\t}\n\n\tvar declaredTotal uint64\n\tfor _, item := range reader.File {\n\t\tif item.UncompressedSize64 > maxLocalPackageFileSize {\n\t\t\treturn errors.New(\"marketplace package contains a file that is too large\")\n\t\t}\n\t\tif ^uint64(0)-declaredTotal < item.UncompressedSize64 {\n\t\t\treturn errors.New(\"marketplace package is too large\")\n\t\t}\n\t\tdeclaredTotal += item.UncompressedSize64\n\t\tif declaredTotal > maxLocalPackageExtractSize {\n\t\t\treturn errors.New(\"marketplace package is too large\")\n\t\t}\n\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/bazaar/local.go#L79-L115","documentation":"The uploaded marketplace package (.zip) opened successfully but contains zero member entries. Thrown by extractLocalPackageArchive (kernel/bazaar/local.go:96-98) right after zip.OpenReader succeeds, as a sanity guard before iterating reader.File. It prevents the rest of the pipeline from operating on a structurally valid but content-less archive.","triggerScenarios":"Calling bazaar.ExtractLocalPackage (or model.InstallLocalBazaarPackage) with archivePath pointing to a valid zip file whose central directory lists no files. The HTTP/API entry point is the local-package install endpoint which forwards the uploaded archive path here.","commonSituations":"The user re-zipped an already-extracted folder but glob matched nothing, a build step emitted an empty archive, or a partially downloaded/corrupt archive happened to parse as a valid empty zip.","solutions":["Inspect the archive with `unzip -l <path>` (or `go tool` / `archive/zip`) and confirm it lists files","Re-create the archive so it actually contains the package payload (manifest + assets)","If generating the zip in CI, verify the file-glob step matched files before zipping"],"exampleFix":"// before: zip created from empty glob\nzip -r pkg.zip ./dist/*   # ./dist/* matched nothing\n\n// after: ensure files exist before zipping\nzip -r pkg.zip plugin.json README.md ./dist","handlingStrategy":"validation","validationCode":"// Run before calling bazaar.ExtractLocalPackage\nfunc assertArchiveNonEmpty(path string) error {\n    r, err := zip.OpenReader(path)\n    if err != nil { return fmt.Errorf(\"not a valid zip: %w\", err) }\n    defer r.Close()\n    if len(r.File) == 0 { return errors.New(\"archive has no entries\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"pkgType, pkg, src, cleanup, err := bazaar.ExtractLocalPackage(archivePath)\nif err != nil {\n    cleanup()\n    // err already carries the specific message; surface to the upload caller\n    return err\n}\ndefer cleanup()","preventionTips":["Validate uploaded archives with archive/zip before forwarding to ExtractLocalPackage","In CI packaging steps, assert `unzip -l pkg.zip | wc -l` > 0 before publishing","Reject zero-byte or empty-zip uploads at the HTTP handler before they reach the kernel"],"tags":["zip","archive","bazaar","marketplace","validation"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}