Budibase/budibase · error · Error

No datasource provided for external query

Error message

No datasource provided for external query

What it means

makeExternalQuery is the core execution path for all SQL/REST integrations in Budibase. Before dispatching a request it enriches and validates the datasource object on the incoming JSON request; if json.datasource is absent or falsy there is no connection to run against, so it throws immediately. This is a programming/configuration bug on the caller's side, not a transient network issue.

Source

Thrown at packages/server/src/integrations/base/query.ts:27

function isEnriched(
  json: QueryJson | EnrichedQueryJson
): json is EnrichedQueryJson {
  return "datasource" in json
}

export async function makeExternalQuery(
  json: QueryJson | EnrichedQueryJson
): Promise<DatasourcePlusQueryResponse> {
  if (!isEnriched(json)) {
    json = await enrichQueryJson(json)
    if (json.datasource) {
      json.datasource = await sdk.datasources.enrich(json.datasource)
    }
  }

  if (!json.datasource) {
    throw new Error("No datasource provided for external query")
  }

  const Integration = await getIntegration(json.datasource.source)

  if (!isDatasourcePlusConstructor(Integration)) {
    throw "Datasource does not support query."
  }

  const integration = new Integration(json.datasource.config)
  return integration.query(json)
}

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Ensure the request payload includes a complete datasource object with at least `_id` and `source` populated before calling makeExternalQuery
  2. Fetch the datasource entity from the DB first (e.g. sdk.datasources.get(datasourceId)) and attach it to json.datasource
  3. If json.datasource should already exist, check the code path that builds the request (makeTableRequest / relationship helpers) for a variable holding the datasource that is undefined
  4. Run the enrich step unconditionally: only skip it when datasource truly won't be needed

Example fix

// before
await makeExternalQuery(ctx, { operation: Operation.READ, table: table })
// after
const datasource = await sdk.datasources.get(table.datasourceId)
await makeExternalQuery(ctx, { datasource, operation: Operation.READ, table: table })
Defensive patterns

Strategy: validation

Validate before calling

function assertDatasource(json) {
  if (!json || !json.datasource || !json.datasource.source) {
    throw new Error('External query requires a datasource with a source')
  }
}
// call before makeExternalQuery(json)

Type guard

function hasDatasource(json) {
  return typeof json === 'object' && json !== null &&
    'datasource' in json && json.datasource != null &&
    typeof json.datasource.source === 'string'
}

Try / catch

try {
  await makeExternalQuery(ctx, json)
} catch (err) {
  if (err.message === 'No datasource provided for external query') {
    // fix payload: fetch + attach datasource, or surface a 400 to the caller
  } else throw err
}

Prevention

When it happens

Trigger: Calling makeExternalQuery (directly or via makeTableRequest, response, run, handleManyRelationships, or the relationship-removal helpers) with a JSON body whose `datasource` property is undefined, null, or was not populated by the caller — e.g. building the request object manually or a datasource fetch returned nothing.

Common situations: Custom scripts or automations constructing external query payloads by hand; an enrich step silently clearing a malformed datasource; API clients calling internal server endpoints without embedding the datasource entity; passing a datasource-less pagination/page request.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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