{"record":{"id":"72bb7397ac97b1e0","repo":"Budibase/budibase","slug":"project-package-is-missing-manifest-json","errorCode":null,"errorMessage":"Project package is missing manifest.json.","messagePattern":"Project package is missing manifest\\.json\\.","errorType":"validation","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/projects/backups/imports.ts","lineNumber":970,"sourceCode":"          ![\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\n        )\n      }),\n    ])\n\n    const [manifest, project, dependencyIndex] = await Promise.all([\n      readJsonFile<ProjectPackageManifest>(manifestPath),\n      readJsonFile<Project>(projectPath),\n      readJsonFile<ProjectPackageDependencyIndex>(dependencyIndexPath),\n    ])\n","sourceCodeStart":952,"sourceCodeEnd":988,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/projects/backups/imports.ts#L952-L988","documentation":"Every project package must include a manifest.json at the archive root. extractProjectPackage() probes for it with fsp.access and, when it is absent, throws this HTTP 400 at imports.ts:969-971. Without the manifest the importer cannot determine package metadata, so the import is rejected.","triggerScenarios":"Importing a package tarball whose root has no manifest.json — the fsp.access(manifestPath) promise rejects at imports.ts:968-971 inside the Promise.all validation.","commonSituations":"Importing an archive of just project docs or a partial extraction; hand-assembling a package and forgetting the manifest; a truncated or corrupted tarball missing entries; importing an artifact type that never had a manifest.","solutions":["Re-export the project package from the source workspace so a valid manifest.json is included","Verify the archive actually contains manifest.json at the root (tar -tf pkg.tgz | grep manifest)","If unarchiving/re-archiving manually, don't drop manifest.json from the root","Re-download the package — the original may have been truncated or corrupted in transit"],"exampleFix":"null","handlingStrategy":"validation","validationCode":"import { createReadStream } from 'fs'\nimport { parse } from 'tar'\nconst hasManifest = await new Promise<boolean>((resolve, reject) => {\n  const ws = parse({ onReadEntry: (e: any) => { if (e.path === 'manifest.json') { resolve(true); ws.abort?.() } }, onEnd: () => resolve(false) })\n  createReadStream(packagePath).pipe(ws as any)\n  ws.on('error', reject)\n})\nif (!hasManifest) throw new Error('package is missing manifest.json at archive root')","typeGuard":"function hasRequiredRootFiles(entries: readonly string[]): entries is readonly string[] {\n  const required = ['manifest.json', 'project.json', 'dependency-index.json']\n  return required.every(f => entries.includes(f))\n}","tryCatchPattern":"try {\n  await importProjectPackage(file)\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 400 && err.message === 'Project package is missing manifest.json.') {\n    // obtain a complete package: re-export from the source workspace\n  } else {\n    throw err\n  }\n}","preventionTips":["Verify package contents (manifest.json, project.json, dependency-index.json, docs) before import","Avoid unarchive/re-archive round trips that can drop root files","Check download completion (size/checksum) to catch truncated archives","Prefer fresh exports over stored/copy-pasted package files"],"tags":["import","missing-file","manifest","http-400"],"backgroundTag":"missing-package-manifest","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}