Budibase/budibase · error · Error

Table updated externally, please re-fetch - ${err.message}

Error message

Table updated externally, please re-fetch - ${err.message}

What it means

When an external SQL query fails because the underlying table 'does not exist' (schema drift between Budibase metadata and the actual datasource), search wraps the error with a message telling the developer the table was updated externally and to re-fetch.

Source

Thrown at packages/server/src/sdk/workspace/rows/search/external.ts:165

      )
    const allowedFields = [...visibleFields, ...PROTECTED_EXTERNAL_COLUMNS]
    processed = processed.map(r => pick(r, allowedFields))

    // need wrapper object for bookmarks etc when paginating
    const response: SearchResponse<Row> = { rows: processed, hasNextPage }
    if (hasNextPage && bookmark != null) {
      response.bookmark = bookmark + processed.length
    }
    if (totalRows != null) {
      response.totalRows = totalRows
    }
    if (paginate && !hasNextPage) {
      response.hasNextPage = false
    }
    return response
  } catch (err: any) {
    if (err.message && err.message.includes("does not exist")) {
      throw new Error(
        `Table updated externally, please re-fetch - ${err.message}`,
        { cause: err }
      )
    } else {
      throw err
    }
  }
}

export async function exportRows(
  options: ExportRowsParams
): Promise<ExportRowsResult> {
  const {
    tableId,
    format,
    columns,
    rowIds,
    query,

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-fetch/sync the datasource schema in Budibase so entities match the live DB
  2. Restore the renamed/dropped table or column in the database
  3. Check the cause err.message to identify which relation/column is missing
  4. Reconfigure the datasource connection if the database changed

Example fix

// before
const res = await sdk.rows.search({ tableId, query }) // throws after external rename
// after
try {
  const res = await sdk.rows.search({ tableId, query })
} catch (e) {
  if (e.message.includes('Table updated externally')) await sdk.datasources.sync(datasourceId)
  else throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

const ds = await sdk.datasources.get(datasourceId)
const liveEntities = Object.keys(ds.entities || {})
if (!liveEntities.includes(tableName)) await sdk.datasources.sync(datasourceId)

Try / catch

try { return await search(...) } catch (e) { if (e.message.includes('Table updated externally')) { await sdk.datasources.sync(datasourceId); return await search(...) } throw e }

Prevention

When it happens

Trigger: Running a search against an external table whose columns/table were renamed or dropped directly in the database after the Budibase datasource was configured.

Common situations: DBA renames a column in Postgres; migrations run outside Budibase; datasource entities cached from a previous schema; table dropped between fetches.

Related errors


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