{"record":{"id":"0945a64e7e1108c0","repo":"remix-run/remix","slug":"update-failed-to-find-row-for-table-gettabl","errorCode":null,"errorMessage":"update() failed to find row for table \"' + getTableName(table) + '\"","messagePattern":"update\\(\\) failed to find row for table \"' \\+ getTableName\\(table\\) \\+ '\"","errorType":"exception","errorClass":"DataTableQueryError","httpStatus":null,"severity":"error","filePath":"packages/data-table/src/lib/database.ts","lineNumber":773,"sourceCode":"    table extends AnyTable,\n    relations extends RelationMapForSourceName<TableName<table>> = {},\n  >(\n    table: table,\n    value: PrimaryKeyInput<table>,\n    changes: Partial<TableRow<table>>,\n    options?: UpdateOptions<table, relations>,\n  ): Promise<TableRowWith<table, LoadedRelationMap<relations>>> {\n    let where = getPrimaryKeyWhere(table, value)\n\n    if (this.capabilities.returning) {\n      let updateResult = (await this.query(asQueryTableInput(table)).where(where).update(changes, {\n        touch: options?.touch,\n        returning: '*',\n      })) as { rows: TableRow<table>[] }\n      let updatedRow = updateResult.rows[0]\n\n      if (!updatedRow) {\n        throw new DataTableQueryError(\n          'update() failed to find row for table \"' + getTableName(table) + '\"',\n        )\n      }\n\n      if (!options?.with) {\n        return updatedRow as TableRowWith<table, LoadedRelationMap<relations>>\n      }\n\n      let loaded = await this.findOne(table, {\n        where: getPrimaryKeyWhereFromRow(table, updatedRow),\n        with: options.with,\n      })\n\n      if (!loaded) {\n        throw new DataTableQueryError(\n          'update() failed to find row for table \"' + getTableName(table) + '\"',\n        )\n      }","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/data-table/src/lib/database.ts#L755-L791","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check existence first (db.find) or design the flow to tolerate a missing row instead of treating no-op updates as exceptions.","Verify the id/where you pass actually identifies an existing row (log it, inspect the table).","For upsert semantics, use the upsert API instead of update."],"exampleFix":"// before\nlet row = await db.update(users, params.id, values)\n\n// after\nlet row = await db.find(users, params.id)\nif (!row) throw new Response('Not Found', { status: 404 })\nrow = await db.update(users, params.id, values)","handlingStrategy":"validation","validationCode":"let existing = await db.find(users, params.id)\nif (!existing) throw new Response('Not Found', { status: 404 })\nlet row = await db.update(users, params.id, values)","typeGuard":null,"tryCatchPattern":"try {\n  await db.update(t, id, values)\n} catch (error) {\n  if (error instanceof DataTableQueryError && /failed to find row/.test(error.message)) {\n    throw new Response('Not Found', { status: 404 })\n  }\n}","preventionTips":["Treat update-misses as 404s in route handlers.","Refresh client state before edits; prefer upsert for create-or-update flows."],"tags":["data-table","update","not-found","concurrency"],"backgroundTag":"row-not-found-after-write","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}