{"record":{"id":"88f099a8da6462d6","repo":"Budibase/budibase","slug":"project-package-contains-invalid-datasource-entiti","errorCode":null,"errorMessage":"Project package contains invalid datasource entities.","messagePattern":"Project package contains invalid datasource entities\\.","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/projects/backups/imports.ts","lineNumber":403,"sourceCode":"  return value\n}\n\nconst remapIdReferences = (value: string, idMap: Map<string, string>) =>\n  [...idMap.entries()].reduce(\n    (remapped, [sourceId, destinationId]) =>\n      remapped.split(`${sourceId}.`).join(`${destinationId}.`),\n    value\n  )\n\nconst getDatasourceEntities = (\n  datasource: Datasource\n): Record<string, Table> => {\n  const entities = datasource.entities\n  if (!entities) {\n    return {}\n  }\n  if (!isRecord(entities)) {\n    throw new HTTPError(\n      \"Project package contains invalid datasource entities.\",\n      400\n    )\n  }\n  for (const entity of Object.values(entities)) {\n    if (!isRecord(entity)) {\n      throw new HTTPError(\n        \"Project package contains invalid datasource entities.\",\n        400\n      )\n    }\n  }\n  return entities\n}\n\nconst normaliseWorkspaceAppUrl = (url?: string) => {\n  const trimmed = url?.trim()\n  if (!trimmed) {","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/projects/backups/imports.ts#L385-L421","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: datasources/ds_internal.json\n{ \"_id\": \"ds_internal\", \"entities\": [] }\n// after\n{ \"_id\": \"ds_internal\", \"entities\": { } }","handlingStrategy":"type-guard","validationCode":"const isRecord = (v: unknown): v is Record<string, unknown> =>\n  typeof v === \"object\" && v !== null && !Array.isArray(v)\n\nfunction datasourceEntitiesValid(doc: { entities?: unknown }): boolean {\n  return doc.entities === undefined || isRecord(doc.entities)\n}","typeGuard":"const isRecord = (value: unknown): value is Record<string, unknown> =>\n  typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nfunction hasRecordEntities(doc: unknown): doc is { entities: Record<string, unknown> } {\n  return isRecord(doc) && isRecord((doc as { entities?: unknown }).entities)\n}","tryCatchPattern":"try {\n  await api.importProjectPackage(file)\n} catch (err) {\n  if (err?.status === 400 && err.message === \"Project package contains invalid datasource entities.\") {\n    // fix or remove `entities` in the offending datasource JSON\n  } else throw err\n}","preventionTips":["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"],"tags":["http-400","json-validation","datasource","schema-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}