{"record":{"id":"895333d081b197f8","repo":"Budibase/budibase","slug":"cannot-fetch-row-by-id-rowid","errorCode":null,"errorMessage":"Cannot fetch row by ID \"${rowId}\"","messagePattern":"Cannot fetch row by ID \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/row/ExternalRequest.ts","lineNumber":303,"sourceCode":"  }\n\n  getTable(tableId: string | undefined): Table | undefined {\n    if (!tableId) {\n      throw new Error(\"Table ID is unknown, cannot find table\")\n    }\n    const { tableName } = breakExternalTableId(tableId)\n    return this.tables[tableName]\n  }\n\n  async getRow(table: Table, rowId: string): Promise<Row> {\n    const response = await makeExternalQuery({\n      endpoint: getEndpoint(table._id!, Operation.READ),\n      filters: this.prepareFilters(rowId, {}, table),\n    })\n    if (Array.isArray(response) && response.length > 0) {\n      return response[0]\n    } else {\n      throw new Error(`Cannot fetch row by ID \"${rowId}\"`)\n    }\n  }\n\n  inputProcessing<T extends Row | undefined>(\n    row: T,\n    table: Table\n  ): { row: T; manyRelationships: ManyRelationship[] } {\n    if (!row) {\n      return { row, manyRelationships: [] }\n    }\n    // we don't really support composite keys for relationships, this is why [0] is used\n    // @ts-ignore\n    const tablePrimary: string = table.primary[0]\n    let newRow: Row = {},\n      manyRelationships: ManyRelationship[] = []\n    for (let [key, field] of Object.entries(table.schema)) {\n      // if set already, or not set just skip it\n      if (row[key] === undefined || newRow[key]) {","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/row/ExternalRequest.ts#L285-L321","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nconst row = await externalRequest.getRow(table, rowId)\n// after\nconst existing = await makeExternalQuery({ endpoint: getEndpoint(table._id!, Operation.READ), filters: { equal: { id: rowId } } })\nif (!Array.isArray(existing) || existing.length === 0) {\n  throw new HTTPError(`Row ${rowId} not found in table ${table._id}`, 404)\n}\nconst row = existing[0]","handlingStrategy":"try-catch","validationCode":"const matches = await makeExternalQuery({ endpoint: getEndpoint(table._id!, Operation.READ), filters: { equal: { [primaryKey]: rowId } } })\nif (!Array.isArray(matches) || matches.length === 0) throw new HTTPError(404)","typeGuard":null,"tryCatchPattern":"try {\n  const row = await externalRequest.getRow(table, rowId)\n} catch (err) {\n  if ((err as Error).message.startsWith(\"Cannot fetch row by ID\")) {\n    throw new HTTPError(`Row ${rowId} not found`, 404)\n  }\n  throw err\n}","preventionTips":["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"],"tags":["server","external-datasource","row-not-found","sql"],"backgroundTag":"row-not-found","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}