Budibase/budibase · error · HTTPError

Project package manifest is invalid.

Error message

Project package manifest is invalid.

What it means

validateManifest is the first gate for an imported project package: the manifest JSON must be a record (object). If the parsed project.json manifest is not an object (null, array, string, number), this 400 error is thrown before any content check. It means the package's manifest structure is fundamentally unreadable.

Source

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

        )
      }
      return generateRowActionsID(tableId)
    }
    case ResourceType.WORKSPACE_APP:
      return docIds.generateWorkspaceAppID()
    case ResourceType.SCREEN:
      return generateScreenID()
    default:
      throw new HTTPError(
        `Project import does not support resource type '${resourceType}'.`,
        400
      )
  }
}

const validateManifest = (manifest: ProjectPackageManifest) => {
  if (!isRecord(manifest)) {
    throw new HTTPError("Project package manifest is invalid.", 400)
  }
  if (manifest.artifactType !== "project") {
    throw new HTTPError("Supplied file is not a Project package.", 400)
  }
  if (manifest.formatVersion !== PROJECT_EXPORT_FORMAT_VERSION) {
    throw new HTTPError(
      `Unsupported Project package format version '${manifest.formatVersion}'.`,
      400
    )
  }
  if (
    !isRecord(manifest.sourceWorkspace) ||
    typeof manifest.sourceWorkspace.id !== "string" ||
    !isRecord(manifest.resourcesByType) ||
    !Array.isArray(manifest.unsupportedContent)
  ) {
    throw new HTTPError("Project package manifest is invalid.", 400)
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-upload the correct .tar.gz project package exported from Budibase.
  2. Re-download the export — the file may be truncated or corrupted.
  3. Inspect the manifest inside the archive and confirm it is a JSON object with artifactType "project".
  4. Verify the export came from a compatible Budibase version.

Example fix

// before: manifest.json containing
["not","an","object"]
// after
{ "artifactType": "project", "formatVersion": 1, "resourcesByType": {}, "unsupportedContent": [] }
Defensive patterns

Strategy: type-guard

Validate before calling

let manifest: unknown
try { manifest = JSON.parse(manifestRaw) } catch { throw new Error("Manifest is not valid JSON") }
if (manifest === null || typeof manifest !== "object" || Array.isArray(manifest)) throw new Error("Manifest must be an object")

Type guard

const isManifestObject = (m: unknown): m is Record<string, unknown> =>
  typeof m === "object" && m !== null && !Array.isArray(m)

Try / catch

try {
  await importProjectPackage(file)
} catch (err) {
  if (err instanceof HTTPError && err.status === 400 && err.message === "Project package manifest is invalid.") {
    // verify the uploaded file is a Budibase project package
  }
  throw err
}

Prevention

When it happens

Trigger: Uploading a file whose manifest is not a JSON object — e.g. an empty file, a plain string, an array, or a file that is not a Budibase project package at all (wrong file selected).

Common situations: Uploading the wrong file (a zip of source code, an app export instead of a project package); a corrupted/truncated download; an export produced by incompatible tooling.

Related errors


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