Budibase/budibase · error · HTTPError
Project package contains invalid datasource entities.
Error message
Project package contains invalid datasource entities.
What it means
getDatasourceEntities extracts the `entities` map (tables) from a datasource document during import. If `entities` is present but not a plain object (not a Record), this HTTPError (400) is thrown — datasource.entities must be an object keyed by table id.
Source
Thrown at packages/server/src/sdk/workspace/projects/backups/imports.ts:403
return value
}
const remapIdReferences = (value: string, idMap: Map<string, string>) =>
[...idMap.entries()].reduce(
(remapped, [sourceId, destinationId]) =>
remapped.split(`${sourceId}.`).join(`${destinationId}.`),
value
)
const getDatasourceEntities = (
datasource: Datasource
): Record<string, Table> => {
const entities = datasource.entities
if (!entities) {
return {}
}
if (!isRecord(entities)) {
throw new HTTPError(
"Project package contains invalid datasource entities.",
400
)
}
for (const entity of Object.values(entities)) {
if (!isRecord(entity)) {
throw new HTTPError(
"Project package contains invalid datasource entities.",
400
)
}
}
return entities
}
const normaliseWorkspaceAppUrl = (url?: string) => {
const trimmed = url?.trim()
if (!trimmed) {View on GitHub (pinned to a81a902e9a)
Solutions
- Fix the datasource JSON so `entities` is a plain object, e.g. `{ "entities": { "ta_x": { ...table } } }`.
- Remove `entities` entirely if the datasource has no inner tables (the function returns {} when absent).
- Re-export the datasource/project from the source app instead of hand-editing.
- Validate all datasource docs pre-import: entities must be a non-array object whose values are objects.
Example fix
// before: datasources/ds_internal.json
{ "_id": "ds_internal", "entities": [] }
// after
{ "_id": "ds_internal", "entities": { } } Defensive patterns
Strategy: type-guard
Validate before calling
const isRecord = (v: unknown): v is Record<string, unknown> =>
typeof v === "object" && v !== null && !Array.isArray(v)
function datasourceEntitiesValid(doc: { entities?: unknown }): boolean {
return doc.entities === undefined || isRecord(doc.entities)
} Type guard
const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null && !Array.isArray(value)
function hasRecordEntities(doc: unknown): doc is { entities: Record<string, unknown> } {
return isRecord(doc) && isRecord((doc as { entities?: unknown }).entities)
} Try / catch
try {
await api.importProjectPackage(file)
} catch (err) {
if (err?.status === 400 && err.message === "Project package contains invalid datasource entities.") {
// fix or remove `entities` in the offending datasource JSON
} else throw err
} Prevention
- Ensure entities is always a plain object (never an array/string) in datasource docs
- Omit `entities` entirely for datasources without inner tables
- Validate datasource JSON shape against the Datasource schema before packaging
- Re-export from the app instead of hand-editing serialized docs
When it happens
Trigger: A datasource doc in the package where `entities` is an array, string, number, or boolean instead of an object — e.g. `{ "entities": [] }` or `{ "entities": "..." }` in a datasource .json.
Common situations: Hand-edited datasource JSON; exports from incompatible versions with a changed entities shape; serialization bugs converting objects to arrays; corrupt/partial doc bodies from failed exports.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Project package contains a doc without an id.
- view is missing queryUI field
- Unknown plugin type - check schema.json: ${schema.type}
- Source table '${relationship.sourceTable}' not found in data
- Target table '${relationship.targetTable}' not found in data
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/88f099a8da6462d6.
Report an issue: GitHub.