remix-run/remix · error · Error

Missing key "{key}" for primary key lookup on "{getTableName

Error message

Missing key "{key}" for primary key lookup on "{getTableName(table)}"

What it means

For composite primary keys, the lookup object must contain every column listed in the table's primaryKey. This error names the exact missing key so you can add it to the object you passed to the lookup API.

Source

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

  value: PrimaryKeyInput<table>,
): Partial<TableRow<table>> {
  let keys = getTablePrimaryKey(table)

  if (keys.length === 1 && (typeof value !== 'object' || value === null || Array.isArray(value))) {
    let key = keys[0] as keyof TableRow<table>
    return { [key]: value } as Partial<TableRow<table>>
  }

  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
    throw new Error('Composite primary keys require an object value')
  }

  let objectValue = value as Record<string, unknown>
  let output: Partial<TableRow<table>> = {}

  for (let key of keys) {
    if (!(key in objectValue)) {
      throw new Error(
        'Missing key "' + key + '" for primary key lookup on "' + getTableName(table) + '"',
      )
    }

    ;(output as Record<string, unknown>)[key] = objectValue[key]
  }

  return output
}

/**
 * Builds a stable key for a row tuple.
 * @param row Source row.
 * @param columns Columns included in the tuple.
 * @returns Stable tuple key.
 */
export function getCompositeKey(row: Record<string, unknown>, columns: readonly string[]): string {
  let values = columns.map((column) => stableSerialize(row[column]))

View on GitHub (pinned to 9696913134)

Solutions

  1. Add the missing key named in the error message to your lookup object
  2. Verify spelling/casing matches the column name in the table definition
  3. Validate incoming params contain all primaryKey columns before the lookup

Example fix

// before
let row = await db.members.find({ tenantId })
// after
let row = await db.members.find({ tenantId, memberId })
Defensive patterns

Strategy: validation

Validate before calling

for (const key of primaryKeyColumns) {
  if (!(key in value)) throw new Error(`missing key ${key}`)
}

Type guard

const hasAllKeys = (v: object, keys: string[]) => keys.every((k) => k in v)

Prevention

When it happens

Trigger: Calling find/update with { tenantId: 'x' } when primaryKey is ['tenantId','postId']; also typos or camelCase/snake_case mismatches in the key name.

Common situations: Partial objects built from URL params that only carry some key segments, or renaming key columns without updating lookup call sites.

Related errors


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