Budibase/budibase · error
Cannot fetch row by ID "${rowId}"
Error message
Cannot fetch row by ID "${rowId}" What it means
getRow fetches a single external-datasource row by issuing a READ query with an equality filter on the row ID. The query executed without error but returned an empty array, meaning no row matched the given ID, so the method throws. It signals a row-not-found condition for external (SQL) datasources.
Source
Thrown at packages/server/src/api/controllers/row/ExternalRequest.ts:303
}
getTable(tableId: string | undefined): Table | undefined {
if (!tableId) {
throw new Error("Table ID is unknown, cannot find table")
}
const { tableName } = breakExternalTableId(tableId)
return this.tables[tableName]
}
async getRow(table: Table, rowId: string): Promise<Row> {
const response = await makeExternalQuery({
endpoint: getEndpoint(table._id!, Operation.READ),
filters: this.prepareFilters(rowId, {}, table),
})
if (Array.isArray(response) && response.length > 0) {
return response[0]
} else {
throw new Error(`Cannot fetch row by ID "${rowId}"`)
}
}
inputProcessing<T extends Row | undefined>(
row: T,
table: Table
): { row: T; manyRelationships: ManyRelationship[] } {
if (!row) {
return { row, manyRelationships: [] }
}
// we don't really support composite keys for relationships, this is why [0] is used
// @ts-ignore
const tablePrimary: string = table.primary[0]
let newRow: Row = {},
manyRelationships: ManyRelationship[] = []
for (let [key, field] of Object.entries(table.schema)) {
// if set already, or not set just skip it
if (row[key] === undefined || newRow[key]) {View on GitHub (pinned to a81a902e9a)
Solutions
- Verify the rowId matches an actual primary-key value in the external table
- Check the table's primary key configuration in the datasource and re-sync the table schema
- Guard deletes/updates with an existence check (query with filters) before calling getRow
Example fix
// before
const row = await externalRequest.getRow(table, rowId)
// after
const existing = await makeExternalQuery({ endpoint: getEndpoint(table._id!, Operation.READ), filters: { equal: { id: rowId } } })
if (!Array.isArray(existing) || existing.length === 0) {
throw new HTTPError(`Row ${rowId} not found in table ${table._id}`, 404)
}
const row = existing[0] Defensive patterns
Strategy: try-catch
Validate before calling
const matches = await makeExternalQuery({ endpoint: getEndpoint(table._id!, Operation.READ), filters: { equal: { [primaryKey]: rowId } } })
if (!Array.isArray(matches) || matches.length === 0) throw new HTTPError(404) Try / catch
try {
const row = await externalRequest.getRow(table, rowId)
} catch (err) {
if ((err as Error).message.startsWith("Cannot fetch row by ID")) {
throw new HTTPError(`Row ${rowId} not found`, 404)
}
throw err
} Prevention
- Verify rowId equals the table's configured primary key value, not a Budibase internal ID
- Check for concurrent deletes before update/delete operations
- Confirm primary key configuration in the datasource after schema changes
When it happens
Trigger: Calling row(), beforeRow() or any update/delete flow that pre-fetches a row, with a rowId that does not exist in the backing SQL table; primary-key mismatch (e.g. passing an _id in Budibase internal format rather than the actual primary key value).
Common situations: Client holding a stale ID after the row was deleted externally; querying by a Budibase internal ID against a SQL table whose PK differs; string/number type mismatch in the filter (e.g. "1" vs 1); another process removed the row concurrently.
Related errors
- Table ID is unknown, cannot find table
- Unable to lookup relationships - undefined column properties
- unable to find related table
- sqs_error
- Invalid Teams app package version
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/895333d081b197f8.
Report an issue: GitHub.