{"record":{"id":"0dd77d94421c7e7a","repo":"Budibase/budibase","slug":"project-package-contains-unsupported-files","errorCode":null,"errorMessage":"Project package contains unsupported files.","messagePattern":"Project package contains unsupported files\\.","errorType":"validation","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/projects/backups/imports.ts","lineNumber":960,"sourceCode":"    }\n    if (rootEntries.includes(\"db.txt\")) {\n      throw new HTTPError(\n        \"Workspace exports cannot be imported as Project packages.\",\n        400\n      )\n    }\n    if (\n      rootEntries.some(\n        entry =>\n          ![\n            PROJECT_MANIFEST_FILE,\n            PROJECT_FILE,\n            PROJECT_DEPENDENCY_INDEX_FILE,\n            PROJECT_DOCS_DIRECTORY,\n          ].includes(entry)\n      )\n    ) {\n      throw new HTTPError(\"Project package contains unsupported files.\", 400)\n    }\n\n    const manifestPath = join(tmpPath, PROJECT_MANIFEST_FILE)\n    const projectPath = join(tmpPath, PROJECT_FILE)\n    const dependencyIndexPath = join(tmpPath, PROJECT_DEPENDENCY_INDEX_FILE)\n    const docsPath = join(tmpPath, PROJECT_DOCS_DIRECTORY)\n\n    await Promise.all([\n      fsp.access(manifestPath).catch(() => {\n        throw new HTTPError(\"Project package is missing manifest.json.\", 400)\n      }),\n      fsp.access(projectPath).catch(() => {\n        throw new HTTPError(\"Project package is missing project.json.\", 400)\n      }),\n      fsp.access(dependencyIndexPath).catch(() => {\n        throw new HTTPError(\n          \"Project package is missing dependency-index.json.\",\n          400","sourceCodeStart":942,"sourceCodeEnd":978,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/projects/backups/imports.ts#L942-L978","documentation":"Project packages must contain only recognized entries: the manifest, project.json, dependency-index.json, and the docs directory (checked at imports.ts:946-961 against the allowed entry list). Any other file or directory in the archive root causes this HTTP 400, guarding against malformed or tampered packages.","triggerScenarios":"Importing a tarball whose root contains files/directories other than the manifest file, PROJECT_FILE, PROJECT_DEPENDENCY_INDEX_FILE, and PROJECT_DOCS_DIRECTORY — the allowlist check at imports.ts:948-959 fails.","commonSituations":"Re-zipping an extracted package and accidentally including extra files (e.g. .DS_Store, __MACOSX, editor backups); adding custom files into the package expecting them to be imported; an export produced by an incompatible tool or version.","solutions":["Rebuild the package so its root contains only manifest.json, project.json, dependency-index.json and the docs directory","Re-export the package from the source workspace instead of hand-assembling it","If re-zipping manually, exclude OS/editor junk (.DS_Store, Thumbs.db, __MACOSX)","Inspect the archive root (tar -tf pkg.tgz | head) to find the offending entry named by the check"],"exampleFix":"null","handlingStrategy":"validation","validationCode":"import { createReadStream } from 'fs'\nimport { parse } from 'tar'\nconst ALLOWED = ['manifest.json', 'project.json', 'dependency-index.json', 'docs']\nconst bad: string[] = []\nawait new Promise<void>((resolve, reject) => {\n  const ws = parse({ onReadEntry: (e: any) => { const root = e.path.split('/')[0]; if (!ALLOWED.includes(root)) bad.push(root) }, onEnd: () => resolve() })\n  createReadStream(packagePath).pipe(ws as any)\n  ws.on('error', reject)\n})\nif (bad.length) throw new Error(`unsupported entries in package root: ${[...new Set(bad)].join(', ')}`)","typeGuard":"function hasOnlyAllowedRootEntries(entries: readonly string[], allowed: readonly string[]): entries is readonly string[] {\n  return entries.every(e => allowed.includes(e))\n}","tryCatchPattern":"try {\n  await importProjectPackage(file)\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 400 && err.message === 'Project package contains unsupported files.') {\n    // inspect archive root, rebuild package with only the allowed entries\n  } else {\n    throw err\n  }\n}","preventionTips":["Never add custom files to a project package; packages are not a general transport","When re-archiving, exclude OS junk (.DS_Store, __MACOSX, Thumbs.db)","Always re-export from the source workspace rather than hand-building packages","List archive contents (tar -tf) before importing"],"tags":["import","archive-validation","http-400"],"backgroundTag":"unsupported-archive-format","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}