{"record":{"id":"4ea30ab3e4d3f348","repo":"Budibase/budibase","slug":"datasource-has-not-been-configured-for-plus-api","errorCode":null,"errorMessage":"Datasource has not been configured for plus API.","messagePattern":"Datasource has not been configured for plus API\\.","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/rows/search/external.ts","lineNumber":215,"sourceCode":"    requestQuery = {\n      oneOf: {\n        _id: rowIds.map((row: string) => {\n          const ids = breakRowIdField(row)\n          if (ids.length > 1) {\n            return ids\n          }\n          return ids[0]\n        }),\n      },\n    }\n  } else {\n    requestQuery = query || {}\n  }\n\n  const datasource = await sdk.datasources.get(datasourceId)\n  const table = await sdk.tables.getTable(tableId)\n  if (!datasource || !datasource.entities) {\n    throw new HTTPError(\"Datasource has not been configured for plus API.\", 400)\n  }\n\n  let result = await search(\n    { tableId: table._id!, query: requestQuery, sort, sortOrder },\n    table\n  )\n  let rows: Row[] = []\n  let headers\n\n  // Filter data to only specified columns if required\n  if (columns && columns.length) {\n    for (let i = 0; i < result.rows.length; i++) {\n      rows[i] = {}\n      for (let column of columns) {\n        rows[i][column] = result.rows[i][column]\n      }\n    }\n    headers = columns","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/rows/search/external.ts#L197-L233","documentation":"exportRows fetches the datasource and checks that it exists and has configured entities (`datasource.entities`). Plus (REST/SQL connector) APIs need entity definitions to run queries; if missing, the export cannot proceed and a 400 is thrown.","triggerScenarios":"Calling exportRows where datasourceId resolves to a datasource with no `entities` map — a plus datasource that was created but never had its tables/schema fetched, or a deleted/corrupt datasource document.","commonSituations":"REST connector configured without running the schema fetch step; datasource doc corrupted or partially migrated; pointing at a datasourceId from a different app; a non-plus datasource mistakenly used with the plus export path.","solutions":["Re-fetch/sync the datasource so its entities are populated","Confirm the datasourceId belongs to a configured plus datasource in this app","Recreate the datasource if the entities document is missing/corrupt","Verify the table exists under datasource.entities before exporting"],"exampleFix":"// before\nawait sdk.rows.exportRows({ tableId }) // datasource never fetched schema\n// after\nconst ds = await sdk.datasources.get(datasourceId)\nif (!ds?.entities) await sdk.datasources.sync(datasourceId)\nawait sdk.rows.exportRows({ tableId })","handlingStrategy":"validation","validationCode":"const ds = await sdk.datasources.get(datasourceId)\nif (!ds || !ds.entities || !Object.keys(ds.entities).length) throw new Error('Datasource entities not configured - run sync')","typeGuard":"function isConfiguredDatasource(ds: Datasource | undefined): ds is Datasource & { entities: Record<string, TableSchema> } { return !!ds && !!ds.entities && Object.keys(ds.entities).length > 0 }","tryCatchPattern":"try { await sdk.rows.exportRows(opts) } catch (e) { if (e.message.includes('not been configured for plus API')) { await sdk.datasources.sync(datasourceId) } else throw e }","preventionTips":["Always sync new plus datasources before querying","Check entities exist after datasource creation","Guard against referencing datasources from other apps"],"tags":["datasource-configuration","plus-api","export"],"backgroundTag":"datasource-not-configured","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}