{"record":{"id":"375d6a2a39a7abcf","repo":"siyuan-note/siyuan","slug":"marketplace-package-contains-too-many-files","errorCode":null,"errorMessage":"marketplace package contains too many files","messagePattern":"marketplace package contains too many files","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/local.go","lineNumber":100,"sourceCode":"\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}\n\n\tif err = os.MkdirAll(destination, 0755); err != nil {\n\t\treturn err","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/bazaar/local.go#L82-L118","documentation":"extractLocalPackageArchive enforces maxLocalPackageFileCount (10000 entries). Archives declaring more entries than this are rejected before any bytes are extracted, protecting the kernel from decompression bombs made of many small files.","triggerScenarios":"Calling ExtractLocalPackage with a zip containing more than 10,000 entries (files + directories counted from reader.File).","commonSituations":"Packaging node_modules or a build cache into the plugin zip; including a vendored dependency tree; accidental inclusion of .git directory with many objects.","solutions":["Exclude node_modules, .git, and caches from the zip","Prune the package to only runtime files required by the manifest","Add exclusion flags when zipping (e.g. zip -r plugin.zip . -x 'node_modules/*' '.git/*')"],"exampleFix":"// before: zip -r plugin.zip .\n// after: zip -r plugin.zip . -x \"node_modules/*\" -x \".git/*\"","handlingStrategy":"validation","validationCode":"const count = Number(execSync(`unzip -l ${zipPath} | tail -1`).toString().match(/(\\d+) files?/)?.[1] ?? 0);\nif (count > 10000) throw new Error(\"too many entries: \" + count);","typeGuard":null,"tryCatchPattern":"try { await installLocalPackage(zipPath); } catch (e) { if (String(e).includes(\"too many files\")) { /* add exclusions and rezip */ } }","preventionTips":["Never zip node_modules or .git","Use explicit exclusion patterns when packaging","Prune to runtime files listed in the manifest"],"tags":["bazaar","zip","limit","resource-exhaustion"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}