{"record":{"id":"5d1a520ee20f55de","repo":"Budibase/budibase","slug":"project-package-contains-too-many-files","errorCode":null,"errorMessage":"Project package contains too many files.","messagePattern":"Project package contains too many files\\.","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/projects/backups/imports.ts","lineNumber":207,"sourceCode":"    if (relPath.split(/[\\\\/]/).length > MAX_PATH_SEGMENTS) {\n      throw new HTTPError(\n        \"Project package contains paths that are too deep.\",\n        400\n      )\n    }\n    if (entry.isSymbolicLink()) {\n      throw new HTTPError(\"Project package contains unsupported links.\", 400)\n    }\n    if (entry.isDirectory()) {\n      files.push(\n        ...(await readDirectoryRecursively(fullPath, rootPath, totals))\n      )\n    } else {\n      const stats = await fsp.stat(fullPath)\n      totals.files += 1\n      totals.bytes += stats.size\n      if (totals.files > MAX_PACKAGE_FILES) {\n        throw new HTTPError(\"Project package contains too many files.\", 400)\n      }\n      if (totals.bytes > MAX_EXTRACTED_SIZE_BYTES) {\n        throw new HTTPError(\"Project package is too large.\", 400)\n      }\n      files.push(fullPath)\n    }\n  }\n\n  return files\n}\n\nconst validateProjectPackageBeforeExtraction = async (file: {\n  path: string\n}) => {\n  const archiveHeader = new Uint8Array(2)\n  const archiveFile = await fsp.open(file.path, \"r\")\n  try {\n    await archiveFile.read(archiveHeader, 0, archiveHeader.length, 0)","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/projects/backups/imports.ts#L189-L225","documentation":"To protect the server, imports enforce a file-count budget (MAX_PACKAGE_FILES) and total uncompressed size (MAX_EXTRACTED_SIZE_BYTES). readDirectoryRecursively increments totals per file and throws this 400 HTTPError as soon as the file count exceeds the cap (the next check throws for total size).","triggerScenarios":"Importing a project package containing more files than MAX_PACKAGE_FILES — e.g. archives that include node_modules, build artifacts, datasets, or other bulk content alongside the actual project resources.","commonSituations":"Accidentally zipping dependency folders; exporting huge apps with many attachments/assets; denial-of-service style archives; automated pipelines bundling extra artifacts into the package.","solutions":["Remove unnecessary content (node_modules, build output, large assets) from the package and re-import","Split very large apps into smaller imports where possible","Check the package file count (tar -tf | wc -l) against the server's limit before importing","If the limit is genuinely too small for your use case, raise MAX_PACKAGE_FILES in a self-hosted fork"],"exampleFix":"// before\ntar -czf app.tar.gz app/        # includes app/node_modules (100k+ files)\n// after\ntar -czf app.tar.gz --exclude='node_modules' app/","handlingStrategy":"validation","validationCode":"const { stdout } = await exec(\"tar -tzf pkg.tar.gz | wc -l\")\nif (Number(stdout) > MAX_PACKAGE_FILES) throw new Error(`Package has ${stdout} files; exceeds import limit`)","typeGuard":"null","tryCatchPattern":"try {\n  await importProject(packagePath)\n} catch (e) {\n  if (e instanceof HTTPError && e.message.includes(\"too many files\")) {\n    // exclude bulky directories, repackage, retry\n  } else throw e\n}","preventionTips":["Exclude node_modules and build artifacts before archiving","Check file count (tar -tf | wc -l) before import","Keep large assets out of app packages"],"tags":["import","validation","limits","backups"],"backgroundTag":"archive-file-limit-exceeded","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}