{"record":{"id":"4ee19acd4cc9b33b","repo":"unslothai/unsloth","slug":"the-pinned-spec-name-archive-has-too-many-entrie","errorCode":null,"errorMessage":"The pinned {spec.name} archive has too many entries","messagePattern":"The pinned (.+?) archive has too many entries","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/utils/third_party_source.py","lineNumber":650,"sourceCode":"        raise RuntimeError(f\"The pinned {spec.name} source archive is not configured\")\n    workspace = Path(tempfile.mkdtemp(prefix = \".archive-\", dir = destination.parent))\n    archive = workspace / \"source.tar.gz\"\n    staging = workspace / \"source\"\n    staging.mkdir()\n    try:\n        _download_archive(spec.archive_url, archive, spec)\n        member_count = 0\n        uncompressed_bytes = 0\n        extracted = set()\n        try:\n            with archive.open(\"rb\") as compressed:\n                with gzip.GzipFile(fileobj = compressed, mode = \"rb\") as decompressed:\n                    reader = _BoundedArchiveReader(decompressed, _ARCHIVE_MAX_TAR_BYTES)\n                    with tarfile.open(fileobj = reader, mode = \"r|\") as bundle:\n                        for member in bundle:\n                            member_count += 1\n                            if member_count > _ARCHIVE_MAX_MEMBERS:\n                                raise RuntimeError(\n                                    f\"The pinned {spec.name} archive has too many entries\"\n                                )\n                            parts = _archive_member_parts(member, spec)\n                            if member.isdir():\n                                continue\n                            if not member.isfile() or member.size < 0:\n                                raise RuntimeError(\n                                    f\"The pinned {spec.name} archive contains a non-regular file\"\n                                )\n                            uncompressed_bytes += member.size\n                            if uncompressed_bytes > _ARCHIVE_MAX_UNCOMPRESSED_BYTES:\n                                raise RuntimeError(\n                                    f\"The pinned {spec.name} archive expands too large\"\n                                )\n                            if len(parts) < 3 or parts[1] != spec.package:\n                                continue\n                            relative = \"/\".join(parts[1:])\n                            _package_path_parts(relative, spec, kind = \"archive\")","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/third_party_source.py#L632-L668","documentation":"Streaming extraction counts tar members; once member_count exceeds _ARCHIVE_MAX_MEMBERS the archive is rejected. This caps filesystem-inode and CPU exhaustion from archives with millions of tiny entries (a classic tar DoS shape) and bounds the extraction loop.","triggerScenarios":"Iterating bundle members in _install_archive_source when the tarball contains more entries than _ARCHIVE_MAX_MEMBERS — either a maliciously generated high-entry-count archive or an unusually large legitimate monorepo snapshot.","commonSituations":"Pinning a huge monorepo's full snapshot instead of a subdirectory export; generated archives containing per-file node_modules-like trees; hostile archive crafted to exhaust inodes.","solutions":["Count entries: tar -tzf source.tar.gz | wc -l and compare with _ARCHIVE_MAX_MEMBERS","Repin to a trimmed export containing only the package subtree (the installer only extracts parts[1] == spec.package anyway)","If the count is legitimate, raise _ARCHIVE_MAX_MEMBERS in your build with awareness of disk/inode impact","Verify the artifact digest against the pin to rule out tampering"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import tarfile\nwith tarfile.open(\"source.tar.gz\") as tf:\n    count = sum(1 for _ in tf)\nassert count <= _ARCHIVE_MAX_MEMBERS, f\"{count} entries exceeds cap\"","typeGuard":null,"tryCatchPattern":"try:\n    ensure_pinned_source(spec)\nexcept RuntimeError as e:\n    if \"too many entries\" in str(e):\n        # switch to a trimmed subtree export rather than raising the member cap blindly","preventionTips":["Pin package-subtree exports, not whole-repo snapshots, to keep entry counts low","Track entry count per pin in CI to catch runaway archives at pin-review time"],"tags":["tarfile","resource-limit","extraction","security"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}