remix-run/remix · error · DataTableQueryError

create({ returnRow: true }) requires primary key values for

Error message

create({ returnRow: true }) requires primary key values for table "' + getTableName(table) + '" when the database does not support RETURNING

What it means

When you call create() with returnRow: true on a database that does not support the SQL RETURNING clause (e.g. older SQLite or MySQL), the library must re-select the inserted row by its primary key. If the values you passed do not include every primary key column, there is no way to locate the row afterwards, so a DataTableQueryError is thrown listing the missing requirement. Supply all primary key values or drop returnRow.

Source

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

    if (Object.prototype.hasOwnProperty.call(values, key)) {
      return {
        [key]: (values as Record<string, unknown>)[key],
      } as SingleTableWhere<table>
    }

    if (insertId !== undefined) {
      return {
        [key]: insertId,
      } as SingleTableWhere<table>
    }
  }

  let where: Record<string, unknown> = {}

  for (let key of primaryKey) {
    if (!Object.prototype.hasOwnProperty.call(values, key)) {
      throw new DataTableQueryError(
        'create({ returnRow: true }) requires primary key values for table "' +
          getTableName(table) +
          '" when the database does not support RETURNING',
      )
    }

    where[key] = (values as Record<string, unknown>)[key]
  }

  return where as SingleTableWhere<table>
}

export function normalizeOrderByInput<table extends AnyTable>(
  input: OrderByInput<table> | undefined,
): OrderByTuple<table>[] {
  if (!input) {
    return []
  }

View on GitHub (pinned to 9696913134)

Solutions

  1. Include every primary key column value in the create() call, e.g. values: { id: crypto.randomUUID(), ...data }
  2. Remove returnRow: true if you don't need the row back and rely on the returned id instead
  3. Switch to a database or driver whose capabilities.returning is true (e.g. Postgres, SQLite 3.35+ with RETURNING enabled)

Example fix

// before
let row = await table.create({
  values: { email: 'a@b.com' },
  returnRow: true,
})

// after
let row = await table.create({
  values: { id: crypto.randomUUID(), email: 'a@b.com' },
  returnRow: true,
})
Defensive patterns

Strategy: validation

Validate before calling

let missing = primaryKeyColumns.filter(k => !(k in values))
if (missing.length > 0 && options?.returnRow && !capabilities.returning) {
  throw new Error('Provide PK values: ' + missing.join(', '))
}

Type guard

function canCreateWithReturnRow(values: Record<string, unknown>, primaryKey: string[], capabilities: { returning: boolean }): boolean {
  return capabilities.returning || primaryKey.every((key) => key in values)
}

Try / catch

try {
  row = await table.create({ values, returnRow: true })
} catch (error) {
  if (error instanceof DataTableQueryError && /primary key values/.test(error.message)) {
    row = await table.row({ where: { id: values.id } }) // after adding id
  } else throw error
}

Prevention

When it happens

Trigger: create({ values, returnRow: true }) where values omits one or more primary key columns, while database.capabilities.returning is false (MySQL, SQLite without RETURNING).

Common situations: Using auto-increment integer primary keys and assuming the database/client generates them, but the table's primary key is client-provided; switching an app from Postgres (RETURNING supported) to MySQL/SQLite without adding PK values; composite primary keys where only part is provided.

Related errors


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