remix-run/remix · error · DataTableQueryError

update() failed to find row for table "' + getTableName(tabl

Error message

update() failed to find row for table "' + getTableName(table) + '"

What it means

update() with returning support executes the UPDATE with returning: '*' and takes rows[0] as the updated row. If the driver reports zero affected rows, this error is thrown — meaning the WHERE clause matched no row, so the update was a no-op.

Source

Thrown at packages/data-table/src/lib/database.ts:773

    table extends AnyTable,
    relations extends RelationMapForSourceName<TableName<table>> = {},
  >(
    table: table,
    value: PrimaryKeyInput<table>,
    changes: Partial<TableRow<table>>,
    options?: UpdateOptions<table, relations>,
  ): Promise<TableRowWith<table, LoadedRelationMap<relations>>> {
    let where = getPrimaryKeyWhere(table, value)

    if (this.capabilities.returning) {
      let updateResult = (await this.query(asQueryTableInput(table)).where(where).update(changes, {
        touch: options?.touch,
        returning: '*',
      })) as { rows: TableRow<table>[] }
      let updatedRow = updateResult.rows[0]

      if (!updatedRow) {
        throw new DataTableQueryError(
          'update() failed to find row for table "' + getTableName(table) + '"',
        )
      }

      if (!options?.with) {
        return updatedRow as TableRowWith<table, LoadedRelationMap<relations>>
      }

      let loaded = await this.findOne(table, {
        where: getPrimaryKeyWhereFromRow(table, updatedRow),
        with: options.with,
      })

      if (!loaded) {
        throw new DataTableQueryError(
          'update() failed to find row for table "' + getTableName(table) + '"',
        )
      }

View on GitHub (pinned to 9696913134)

Solutions

  1. Check existence first (db.find) or design the flow to tolerate a missing row instead of treating no-op updates as exceptions.
  2. Verify the id/where you pass actually identifies an existing row (log it, inspect the table).
  3. For upsert semantics, use the upsert API instead of update.

Example fix

// before
let row = await db.update(users, params.id, values)

// after
let row = await db.find(users, params.id)
if (!row) throw new Response('Not Found', { status: 404 })
row = await db.update(users, params.id, values)
Defensive patterns

Strategy: validation

Validate before calling

let existing = await db.find(users, params.id)
if (!existing) throw new Response('Not Found', { status: 404 })
let row = await db.update(users, params.id, values)

Try / catch

try {
  await db.update(t, id, values)
} catch (error) {
  if (error instanceof DataTableQueryError && /failed to find row/.test(error.message)) {
    throw new Response('Not Found', { status: 404 })
  }
}

Prevention

When it happens

Trigger: db.update(table, idOrWhere, values) where the target row does not exist (already deleted, wrong id, or where matches nothing); concurrent deletion between a read and the update.

Common situations: Optimistic UI updating a record another request deleted; stale ids from previous page state; where clauses built from optional filters that end up matching nothing.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/0945a64e7e1108c0. Report an issue: GitHub.