Budibase/budibase · error · HTTPError

Project package is missing project.json.

Error message

Project package is missing project.json.

What it means

Project packages must contain a project.json file at the archive root alongside the manifest. extractProjectPackage() checks it with fsp.access in the Promise.all at imports.ts:966-982 and throws this HTTP 400 at imports.ts:972-974 when the file is missing. project.json holds the project definition, so its absence makes the package unimportable.

Source

Thrown at packages/server/src/sdk/workspace/projects/backups/imports.ts:973

            PROJECT_DEPENDENCY_INDEX_FILE,
            PROJECT_DOCS_DIRECTORY,
          ].includes(entry)
      )
    ) {
      throw new HTTPError("Project package contains unsupported files.", 400)
    }

    const manifestPath = join(tmpPath, PROJECT_MANIFEST_FILE)
    const projectPath = join(tmpPath, PROJECT_FILE)
    const dependencyIndexPath = join(tmpPath, PROJECT_DEPENDENCY_INDEX_FILE)
    const docsPath = join(tmpPath, PROJECT_DOCS_DIRECTORY)

    await Promise.all([
      fsp.access(manifestPath).catch(() => {
        throw new HTTPError("Project package is missing manifest.json.", 400)
      }),
      fsp.access(projectPath).catch(() => {
        throw new HTTPError("Project package is missing project.json.", 400)
      }),
      fsp.access(dependencyIndexPath).catch(() => {
        throw new HTTPError(
          "Project package is missing dependency-index.json.",
          400
        )
      }),
    ])

    const [manifest, project, dependencyIndex] = await Promise.all([
      readJsonFile<ProjectPackageManifest>(manifestPath),
      readJsonFile<Project>(projectPath),
      readJsonFile<ProjectPackageDependencyIndex>(dependencyIndexPath),
    ])

    validateManifest(manifest)
    validateProject(project)
    validateDependencyIndexShape(dependencyIndex)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-export the project package from the source workspace so project.json is included
  2. Check the archive root contains project.json (tar -tf pkg.tgz | grep project.json)
  3. If re-archiving manually, keep project.json at the archive root with its original name
  4. Re-download the package in case the original transfer was corrupted

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

import { createReadStream } from 'fs'
import { parse } from 'tar'
const hasProjectJson = await new Promise<boolean>((resolve, reject) => {
  const ws = parse({ onReadEntry: (e: any) => { if (e.path === 'project.json') { resolve(true); ws.abort?.() } }, onEnd: () => resolve(false) })
  createReadStream(packagePath).pipe(ws as any)
  ws.on('error', reject)
})
if (!hasProjectJson) throw new Error('package is missing project.json at archive root')

Type guard

function isCompleteProjectPackage(entries: readonly string[]): boolean {
  return ['manifest.json', 'project.json', 'dependency-index.json'].every(f => entries.includes(f))
}

Try / catch

try {
  await importProjectPackage(file)
} catch (err) {
  if (err instanceof HTTPError && err.status === 400 && err.message === 'Project package is missing project.json.') {
    // re-export a complete package from the source workspace
  } else {
    throw err
  }
}

Prevention

When it happens

Trigger: Importing a package tarball whose root lacks project.json — fsp.access(projectPath) rejects and the catch converts it to this HTTP 400.

Common situations: Hand-editing or re-zipping an extracted package and deleting/renaming project.json; importing a docs-only or partial archive; truncated downloads that omitted entries; older exports with a different layout.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/f75d21abeaca8071. Report an issue: GitHub.