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
- Re-fetch/sync the datasource schema in Budibase so entities match the live DB
- Restore the renamed/dropped table or column in the database
- Check the cause err.message to identify which relation/column is missing
- 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
- Sync datasources after external DB migrations
- Monitor for 'does not exist' errors as a sync trigger
- Avoid renaming/dropping tables without updating Budibase
- Cache datasource metadata with a TTL
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
- sqs_error
- Table ID is unknown, cannot find table
- Cannot fetch row by ID "${rowId}"
- Cannot delete rows through a calculation view
- Cannot execute multiple queries for agent log search
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/f49e9e9db038d44a.
Report an issue: GitHub.